-fixing misc minor ats test/driver bugs
[oweals/gnunet.git] / src / ats / perf_ats_solver.c
1 /*
2  This file is part of GNUnet.
3  (C) 2010,2011 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/perf_ats_solver.c
22  * @brief generic performance test for ATS solvers
23  * @author Christian Grothoff
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_statistics_service.h"
29 #include "gnunet-service-ats_addresses.h"
30 #include "gnunet-service-ats_normalization.h"
31 #include "gnunet_ats_service.h"
32 #include "gnunet_ats_plugin.h"
33 #include "test_ats_api_common.h"
34
35 #define DEFAULT_UPDATE_PERCENTAGE       20
36 #define DEFAULT_PEERS_START     10
37 #define DEFAULT_PEERS_END       10
38 #define DEFAULT_ADDRESSES       10
39 #define DEFAULT_ATS_COUNT       2
40
41
42 /**
43  * Handle for ATS address component
44  */
45 struct PerfHandle
46 {
47   /**
48    * Performance peers
49    */
50   struct PerfPeer *peers;
51
52   /**
53    *  Solver handle
54    */
55   void *solver;
56
57   /**
58    * Statistics stat;
59    */
60   struct GNUNET_STATISTICS_Handle *stat;
61
62   /**
63    * A multihashmap to store all addresses
64    */
65   struct GNUNET_CONTAINER_MultiPeerMap *addresses;
66
67   /**
68    * Solver functions
69    * */
70   struct GNUNET_ATS_PluginEnvironment env;
71
72   /**
73    * Array for results for each iteration with length iterations
74    */
75   struct Iteration *iterations_results;
76
77   /**
78    * The current result
79    */
80   struct Result *current_result;
81
82   /**
83    * Current number of peers benchmarked
84    */
85   int current_p;
86
87   /**
88    * Current number of addresses benchmarked
89    */
90   int current_a;
91
92   /**
93    * Solver description as string
94    */
95   char *ats_string;
96
97   /**
98    * Configured ATS solver
99    */
100   int ats_mode;
101
102   /**
103    * #peers to start benchmarking with
104    */
105   int N_peers_start;
106
107   /**
108    * #peers to end benchmarking with
109    */
110   int N_peers_end;
111
112   /**
113    * #addresses to benchmarking with
114    */
115   int N_address;
116
117   /**
118    * Percentage of peers to update
119    */
120   int opt_update_percent;
121
122   /**
123    * Create gnuplot file
124    */
125   int create_datafile;
126
127   /**
128    * Measure updates
129    */
130   int measure_updates;
131
132   /**
133    * Number of iterations
134    */
135   int total_iterations;
136
137   /**
138    * Current iteration
139    */
140   int current_iteration;
141
142   /**
143    * Is a bulk operation running?
144    */
145   int bulk_running;
146
147   /**
148    * Is a bulk operation running?
149    */
150   int expecting_solution;
151
152   /**
153    * Was the problem just updates?
154    */
155   int performed_update;
156 };
157
158 /**
159  * Data structure to store results for a single iteration
160  */
161 struct Iteration
162 {
163   struct Result **results_array;
164
165   struct Result **update_results_array;
166 };
167
168
169 /**
170  * Result for a solver calculcation
171  */
172 struct Result
173 {
174   /**
175    * Previous element in the linked list
176    */
177   struct Result *prev;
178
179   /**
180    * Next element in the linked list
181    */
182   struct Result *next;
183
184   /**
185    * Number of peers this solution included
186    */
187   int peers;
188
189   /**
190    * Number of addresses per peer this solution included
191    */
192   int addresses;
193
194   /**
195    * Is this an update or a full solution
196    */
197   int update;
198
199   /**
200    * Was the solution valid or did the solver fail
201    */
202   int valid;
203
204   /**
205    * Result of the solver
206    */
207   enum GAS_Solver_Additional_Information info;
208
209   /**
210    * Duration of setting up the problem in the solver
211    */
212   struct GNUNET_TIME_Relative d_setup_full;
213
214   /**
215    * Duration of solving the LP problem in the solver
216    * MLP solver only
217    */
218   struct GNUNET_TIME_Relative d_lp_full;
219
220   /**
221    * Duration of solving the MLP problem in the solver
222    * MLP solver only
223    */
224   struct GNUNET_TIME_Relative d_mlp_full;
225
226   /**
227    * Duration of solving whole problem in the solver
228    */
229   struct GNUNET_TIME_Relative d_total_full;
230
231   /**
232    * Start time of setting up the problem in the solver
233    */
234   struct GNUNET_TIME_Absolute s_setup;
235
236   /**
237    * Start time of solving the LP problem in the solver
238    * MLP solver only
239    */
240   struct GNUNET_TIME_Absolute s_lp;
241
242   /**
243    * Start time of solving the MLP problem in the solver
244    * MLP solver only
245    */
246   struct GNUNET_TIME_Absolute s_mlp;
247
248   /**
249    * Start time of solving whole problem in the solver
250    */
251   struct GNUNET_TIME_Absolute s_total;
252
253   /**
254    * End time of setting up the problem in the solver
255    */
256   struct GNUNET_TIME_Absolute e_setup;
257
258   /**
259    * End time of solving the LP problem in the solver
260    * MLP solver only
261    */
262   struct GNUNET_TIME_Absolute e_lp;
263
264   /**
265    * End time of solving the MLP problem in the solver
266    * MLP solver only
267    */
268   struct GNUNET_TIME_Absolute e_mlp;
269
270   /**
271    * End time of solving whole problem in the solver
272    */
273   struct GNUNET_TIME_Absolute e_total;
274 };
275
276 /**
277  * Peer used for the benchmarking
278  */
279 struct PerfPeer
280 {
281   /**
282    * Peer identitity
283    */
284   struct GNUNET_PeerIdentity id;
285
286   /**
287    * Head of linked list of addresses used with this peer
288    */
289   struct ATS_Address *head;
290
291   /**
292    * Head of linked list of addresses used with this peer
293    */
294   struct ATS_Address *tail;
295 };
296
297
298 /**
299  * ATS performance handle
300  */
301 static struct PerfHandle ph;
302
303 /**
304  * Return value
305  */
306 static int ret;
307
308
309 /**
310  * Do shutdown
311  */
312 static void
313 end_now (int res)
314 {
315   if (NULL != ph.stat)
316   {
317     GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
318     ph.stat = NULL;
319   }
320
321   GNUNET_free_non_null (ph.peers);
322   GNUNET_free_non_null (ph.iterations_results);
323
324   GAS_normalization_stop ();
325   ret = res;
326 }
327
328
329 /**
330  * Create a peer used for benchmarking
331  *
332  * @param cp the number of the peer
333  */
334 static void
335 perf_create_peer (int cp)
336 {
337
338   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
339       &ph.peers[cp].id, sizeof (struct GNUNET_PeerIdentity));
340   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Creating peer #%u: %s \n", cp,
341       GNUNET_i2s (&ph.peers[cp].id));
342 }
343
344
345 /**
346  * Perform an update for an address
347  *
348  * @param cur the address to update
349  */
350 static void
351 perf_update_address (struct ATS_Address *cur)
352 {
353   int r_type;
354   int abs_val;
355   double rel_val;
356
357   r_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2);
358   switch (r_type)
359   {
360   case 0:
361     abs_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
362     rel_val = (100 + (double) abs_val) / 100;
363
364     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
365         "Updating peer `%s' address %p type %s abs val %u rel val %.3f\n",
366         GNUNET_i2s (&cur->peer), cur,
367         "GNUNET_ATS_QUALITY_NET_DELAY",
368         abs_val, rel_val);
369     ph.env.sf.s_address_update_property (ph.solver, cur,
370         GNUNET_ATS_QUALITY_NET_DELAY,
371         abs_val, rel_val);
372     break;
373   case 1:
374     abs_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10);
375     rel_val = (100 + (double) abs_val) / 100;
376
377     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
378         "Updating peer `%s' address %p type %s abs val %u rel val %.3f\n",
379         GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DISTANCE",
380         abs_val, rel_val);
381     ph.env.sf.s_address_update_property (ph.solver, cur,
382         GNUNET_ATS_QUALITY_NET_DISTANCE,
383         abs_val, rel_val);
384     break;
385   default:
386     break;
387   }
388   ph.env.sf.s_address_update_inuse (ph.solver, cur, GNUNET_YES);
389 }
390
391
392 static void
393 bandwidth_changed_cb (void *cls,
394                       struct ATS_Address *address)
395 {
396   if ( (0 == address->assigned_bw_out) && (0 == address->assigned_bw_in) )
397     return;
398
399   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
400               "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
401               GNUNET_i2s (&address->peer),
402               address,
403               address->assigned_bw_out,
404               address->assigned_bw_in);
405   if (GNUNET_YES == ph.bulk_running)
406     GNUNET_break (0);
407   return;
408 }
409
410
411 const double *
412 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
413 {
414   return GAS_normalization_get_preferences_by_peer (id);
415 }
416
417
418 const double *
419 get_property_cb (void *cls, const struct ATS_Address *address)
420 {
421   return GAS_normalization_get_properties ((struct ATS_Address *) address);
422 }
423
424 static void
425 normalized_property_changed_cb (void *cls, struct ATS_Address *peer,
426     uint32_t type, double prop_rel)
427 {
428   /* TODO */
429 }
430
431 static void
432 perf_address_initial_update (void *solver,
433     struct GNUNET_CONTAINER_MultiPeerMap * addresses,
434     struct ATS_Address *address)
435 {
436   double delay;
437   double distance;
438   uint32_t random = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
439   delay = (100 + (double) random) / 100;
440   ph.env.sf.s_address_update_property (solver, address, GNUNET_ATS_QUALITY_NET_DELAY,
441       100,  delay);
442
443   random = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
444   distance = (100 + (double) random) / 100;
445
446   ph.env.sf.s_address_update_property (solver, address,
447       GNUNET_ATS_QUALITY_NET_DISTANCE, 10, distance);
448
449   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
450       "Initial update address %p : %.2f  %.2f\n", address, delay, distance);
451 }
452
453 /**
454  * Update a certain percentage of peers
455  *
456  * @param cp the current number of peers
457  * @param ca the current number of addresses
458  * @param percentage_peers the percentage of peers to update
459  */
460
461 static void
462 perf_update_all_addresses (unsigned int cp, unsigned int ca, unsigned int percentage_peers)
463 {
464   struct ATS_Address *cur_address;
465   int c_peer;
466   int c_select;
467   int c_cur_p;
468   int c_cur_a;
469   int r;
470   int count;
471   unsigned int m[cp];
472
473   count = cp * ((double) percentage_peers / 100);
474   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
475       "Updating %u of %u peers \n", count, cp);
476
477   for (c_peer = 0; c_peer < cp; c_peer++)
478     m[c_peer] = 0;
479
480   c_select = 0;
481
482   while (c_select < count)
483   {
484     r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, cp);
485     if (0 == m[r])
486     {
487       m[r] = 1;
488       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
489           "Updating peer [%u] \n", r);
490       c_select++;
491     }
492   }
493   for (c_cur_p = 0; c_cur_p < cp; c_cur_p++)
494   {
495     if (1 == m[c_cur_p])
496     {
497       r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, ca);
498       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
499           "Updating peer [%u] address [%u]\n", c_cur_p, r);
500
501       c_cur_a = 0;
502       for (cur_address = ph.peers[c_cur_p].head; NULL != cur_address; cur_address = cur_address->next)
503       {
504         if (c_cur_a == r)
505           perf_update_address (cur_address);
506         c_cur_a ++;
507       }
508     }
509   }
510 }
511
512 /**
513  * Create an address for a peer
514  *
515  * @param cp index of the peer
516  * @param ca index of the address
517  * @return the address
518  */
519 static struct ATS_Address *
520 perf_create_address (int cp, int ca)
521 {
522   struct ATS_Address *a;
523   a = create_address (&ph.peers[cp].id,
524       "Test 1", "test 1", strlen ("test 1") + 1, 0);
525   GNUNET_CONTAINER_DLL_insert (ph.peers[cp].head, ph.peers[cp].tail, a);
526   GNUNET_CONTAINER_multipeermap_put (ph.addresses, &ph.peers[cp].id, a,
527       GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
528   return a;
529 }
530
531
532 /**
533  * Information callback for the solver
534  *
535  * @param op the solver operation
536  * @param stat status of the solver operation
537  * @param add additional solver information
538  */
539 static void
540 solver_info_cb (void *cls,
541     enum GAS_Solver_Operation op,
542     enum GAS_Solver_Status stat,
543     enum GAS_Solver_Additional_Information add)
544 {
545   char *add_info;
546   switch (add) {
547     case GAS_INFO_NONE:
548       add_info = "GAS_INFO_NONE";
549       break;
550     case GAS_INFO_FULL:
551       add_info = "GAS_INFO_MLP_FULL";
552       break;
553     case GAS_INFO_UPDATED:
554       add_info = "GAS_INFO_MLP_UPDATED";
555       break;
556     case GAS_INFO_PROP_ALL:
557       add_info = "GAS_INFO_PROP_ALL";
558       break;
559     case GAS_INFO_PROP_SINGLE:
560       add_info = "GAS_INFO_PROP_SINGLE";
561       break;
562     default:
563       add_info = "INVALID";
564       break;
565   }
566
567   struct Result *tmp;
568   switch (op)
569   {
570     case GAS_OP_SOLVE_START:
571       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
572           "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START",
573           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
574       if (GNUNET_NO == ph.expecting_solution)
575       {
576         /* We do not expect a solution at the moment */
577         GNUNET_break (0);
578         return;
579       }
580
581       if ((GAS_STAT_SUCCESS == stat) && (NULL == ph.current_result))
582       {
583         tmp = GNUNET_new (struct Result);
584         /* Create new result */
585         if ((add == GAS_INFO_UPDATED) || (GNUNET_YES == ph.performed_update))
586         {
587           ph.current_result = tmp;
588           //fprintf (stderr,"UPDATE %u %u\n",ph.current_iteration-1, ph.current_p);
589           ph.iterations_results[ph.current_iteration-1].update_results_array[ph.current_p] = tmp;
590         }
591         else
592         {
593           ph.current_result = tmp;
594           //fprintf (stderr,"FULL %u %u\n",ph.current_iteration-1, ph.current_p);
595           ph.iterations_results[ph.current_iteration-1].results_array[ph.current_p] = tmp;
596         }
597
598         ph.current_result->addresses = ph.current_a;
599         ph.current_result->peers = ph.current_p;
600         ph.current_result->s_total = GNUNET_TIME_absolute_get();
601         ph.current_result->d_total_full = GNUNET_TIME_UNIT_FOREVER_REL;
602         ph.current_result->d_setup_full = GNUNET_TIME_UNIT_FOREVER_REL;
603         ph.current_result->d_lp_full = GNUNET_TIME_UNIT_FOREVER_REL;
604         ph.current_result->d_mlp_full = GNUNET_TIME_UNIT_FOREVER_REL;
605         ph.current_result->info = add;
606         if ((add == GAS_INFO_UPDATED) || (GNUNET_YES == ph.performed_update))
607         {
608           ph.current_result->update = GNUNET_YES;
609         }
610         else
611         {
612           ph.current_result->update = GNUNET_NO;
613         }
614
615       }
616       return;
617     case GAS_OP_SOLVE_STOP:
618       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
619           "Solver notifies `%s' with result `%s', `%s'\n", "GAS_OP_SOLVE_STOP",
620           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
621       if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
622       {
623         /* We do not expect a solution at the moment */
624         GNUNET_break (0);
625         return;
626       }
627
628       if (GAS_STAT_SUCCESS == stat)
629         ph.current_result->valid = GNUNET_YES;
630       else
631         ph.current_result->valid = GNUNET_NO;
632
633       if (NULL != ph.current_result)
634       {
635         /* Finalize result */
636         ph.current_result->e_total = GNUNET_TIME_absolute_get ();
637         ph.current_result->d_total_full = GNUNET_TIME_absolute_get_difference (
638             ph.current_result->s_total, ph.current_result->e_total);
639       }
640       ph.current_result = NULL;
641       return;
642
643     case GAS_OP_SOLVE_SETUP_START:
644       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
645           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START",
646           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
647       if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
648       {
649         GNUNET_break(0);
650         return;
651       }
652
653       if (GAS_STAT_SUCCESS == stat)
654         ph.current_result->valid = GNUNET_YES;
655       else
656         ph.current_result->valid = GNUNET_NO;
657
658       ph.current_result->s_setup = GNUNET_TIME_absolute_get ();
659       return;
660
661     case GAS_OP_SOLVE_SETUP_STOP:
662       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
663           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP",
664           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
665       if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
666       {
667         GNUNET_break(0);
668         return;
669       }
670
671       if (GAS_STAT_SUCCESS == stat)
672         ph.current_result->valid = GNUNET_YES;
673       else
674         ph.current_result->valid = GNUNET_NO;
675
676       ph.current_result->e_setup = GNUNET_TIME_absolute_get ();
677       ph.current_result->d_setup_full = GNUNET_TIME_absolute_get_difference (
678           ph.current_result->s_setup, ph.current_result->e_setup);
679       return;
680
681     case GAS_OP_SOLVE_MLP_LP_START:
682       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
683           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START",
684           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
685       if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
686       {
687         GNUNET_break(0);
688         return;
689       }
690
691       if (GAS_STAT_SUCCESS == stat)
692         ph.current_result->valid = GNUNET_YES;
693       else
694         ph.current_result->valid = GNUNET_NO;
695
696       ph.current_result->s_lp = GNUNET_TIME_absolute_get ();
697       return;
698     case GAS_OP_SOLVE_MLP_LP_STOP:
699       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
700           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP",
701           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
702       if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
703       {
704         GNUNET_break(0);
705         return;
706       }
707
708       if (GAS_STAT_SUCCESS == stat)
709         ph.current_result->valid = GNUNET_YES;
710       else
711         ph.current_result->valid = GNUNET_NO;
712
713       ph.current_result->e_lp = GNUNET_TIME_absolute_get ();
714       ph.current_result->d_lp_full = GNUNET_TIME_absolute_get_difference (
715           ph.current_result->s_lp, ph.current_result->e_lp);
716       return;
717
718     case GAS_OP_SOLVE_MLP_MLP_START:
719       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
720           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START",
721           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
722       if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
723       {
724         GNUNET_break(0);
725         return;
726       }
727
728       if (GAS_STAT_SUCCESS == stat)
729         ph.current_result->valid = GNUNET_YES;
730       else
731         ph.current_result->valid = GNUNET_NO;
732
733       ph.current_result->s_mlp = GNUNET_TIME_absolute_get ();
734       return;
735     case GAS_OP_SOLVE_MLP_MLP_STOP:
736       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
737           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP",
738           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
739       if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
740       {
741         GNUNET_break(0);
742         return;
743       }
744
745       if (GAS_STAT_SUCCESS == stat)
746         ph.current_result->valid = GNUNET_YES;
747       else
748         ph.current_result->valid = GNUNET_NO;
749
750       ph.current_result->e_mlp = GNUNET_TIME_absolute_get ();
751       ph.current_result->d_mlp_full = GNUNET_TIME_absolute_get_difference (
752       ph.current_result->s_mlp, ph.current_result->e_mlp);
753       return;
754     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
755       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
756           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
757           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
758       return;
759     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
760       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
761           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
762           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
763       if (GAS_STAT_SUCCESS != stat)
764       {
765         GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
766             "Solver `%s' failed to update problem with %u peers and %u address!\n",
767             ph.ats_string, ph.current_p, ph.current_a);
768       }
769
770       return;
771     default:
772       break;
773     }
774 }
775
776 /**
777  * Evaluate results for a specific iteration
778  *
779  * @param iteration the iteration to evaluate
780  */
781 static void
782 evaluate (int iteration)
783 {
784   struct Result *cur;
785   int cp;
786
787   for (cp = ph.N_peers_start; cp <= ph.N_peers_end; cp ++)
788   {
789     cur = ph.iterations_results[ph.current_iteration-1].results_array[cp];
790     if (0 == cp)
791       continue;
792     if (NULL == cur)
793     {
794       GNUNET_break (0);
795       fprintf (stderr,
796                "Missing result for %u peers\n", cp);
797       continue;
798     }
799
800
801     if (GNUNET_NO == cur->valid)
802     {
803       fprintf (stderr,
804                "Total time to solve %s for %u peers %u addresses: %s\n",
805                (GNUNET_YES == cur->update) ? "updated" : "full",
806                cur->peers, cur->addresses, "Failed to solve!");
807       continue;
808     }
809
810
811     if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_total_full.rel_value_us)
812     {
813       fprintf (stderr,
814          "Total time to solve %s for %u peers %u addresses: %llu us\n",
815          (GNUNET_YES == cur->update) ? "updated" : "full",
816          cur->peers, cur->addresses,
817          (unsigned long long) cur->d_total_full.rel_value_us);
818     }
819
820
821     if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_setup_full.rel_value_us)
822     {
823       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
824           "Total time to setup %s %u peers %u addresses: %llu us\n",
825           (GNUNET_YES == cur->update) ? "updated" : "full",
826           cur->peers, cur->addresses,
827           (unsigned long long) cur->d_setup_full.rel_value_us);
828     }
829
830     if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_lp_full.rel_value_us)
831     {
832       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
833          "Total time to solve %s LP for %u peers %u addresses: %llu us\n",
834          (GNUNET_YES == cur->update) ? "updated" : "full",
835          cur->peers,
836          cur->addresses,
837          (unsigned long long )cur->d_lp_full.rel_value_us);
838     }
839
840     if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_mlp_full.rel_value_us)
841     {
842       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
843           "Total time to solve %s MLP for %u peers %u addresses: %llu us\n",
844           (GNUNET_YES == cur->update) ? "updated" : "full",
845           cur->peers, cur->addresses,
846           (unsigned long long )cur->d_mlp_full.rel_value_us);
847     }
848   }
849 }
850
851
852 /**
853  * Evaluate average results for all iterations
854  */
855 static void
856 write_all_iterations (void)
857 {
858   int c_iteration;
859   int c_peer;
860
861   struct GNUNET_DISK_FileHandle *f_full;
862   struct GNUNET_DISK_FileHandle *f_update;
863   char * data_fn_full;
864   char * data_fn_update;
865   char * data;
866
867   f_full = NULL;
868   f_update = NULL;
869
870   data_fn_full = NULL;
871
872   if (GNUNET_NO == ph.create_datafile)
873     return;
874
875   GNUNET_asprintf (&data_fn_full,
876                    "perf_%s_full_%u-%u_%u_%u.data",
877                    ph.ats_string,
878                    ph.total_iterations,
879                    ph.N_peers_start,
880                    ph.N_peers_end,
881                    ph.N_address);
882   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
883               "Using data file `%s'\n",
884               data_fn_full);
885
886   f_full = GNUNET_DISK_file_open (data_fn_full,
887       GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
888       GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
889   if (NULL == f_full)
890   {
891     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
892                 "Cannot open data file `%s'\n",
893                 data_fn_full);
894     GNUNET_free (data_fn_full);
895     return;
896   }
897
898   data = "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n";
899   if (GNUNET_SYSERR == GNUNET_DISK_file_write(f_full, data, strlen(data)))
900     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
901                 "Cannot write data to log file `%s'\n",
902                 data_fn_full);
903
904   data_fn_update = NULL;
905   if (GNUNET_YES == ph.measure_updates)
906   {
907     GNUNET_asprintf (&data_fn_update, "perf_%s_update_%u-%u_%u_%u.data",
908         ph.ats_string,
909         ph.total_iterations,
910         ph.N_peers_start,
911         ph.N_peers_end,
912         ph.N_address);
913     f_update = GNUNET_DISK_file_open (data_fn_update,
914         GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE,
915         GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
916     if (NULL == f_update)
917     {
918       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
919                   "Cannot open gnuplot file `%s'\n", data_fn_update);
920       GNUNET_free (data_fn_update);
921       if (NULL != f_full)
922         GNUNET_DISK_file_close (f_full);
923       GNUNET_free (data_fn_full);
924       return;
925     }
926
927     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
928                 "Using update data file `%s'\n",
929                 data_fn_update);
930
931     data = "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n";
932     if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data, strlen(data)))
933       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
934                   "Cannot write data to log file `%s'\n",
935                   data_fn_update);
936   }
937
938   for (c_peer = ph.N_peers_start; c_peer <= ph.N_peers_end; c_peer ++)
939   {
940     char * data_str;
941     char * data_tmp;
942     char * data_upd_str;
943     char * data_upd_tmp;
944     GNUNET_asprintf(&data_str, "%u;%u",c_peer, ph.N_address);
945     if (ph.measure_updates)
946       GNUNET_asprintf(&data_upd_str, "%u;%u",c_peer, ph.N_address);
947     for (c_iteration = 0; c_iteration < ph.total_iterations; c_iteration ++)
948     {
949       struct Result *cur_full_res;
950       struct Result *cur_upd_res;
951
952
953
954       //fprintf (stderr, "P: %u I: %u  == %p \n", c_peer, c_iteration, cur_res);
955       cur_full_res = ph.iterations_results[c_iteration].results_array[c_peer];
956       if (c_peer == 0)
957         continue;
958       if (NULL == cur_full_res)
959         continue;
960
961       if (ph.measure_updates)
962       {
963         cur_upd_res = ph.iterations_results[c_iteration].update_results_array[c_peer];
964         data_upd_tmp = GNUNET_strdup (data_upd_str);
965         GNUNET_free (data_upd_str);
966         if (GNUNET_YES == cur_full_res->valid)
967         {
968           GNUNET_asprintf (&data_upd_str, "%s;%llu", data_upd_tmp,
969             (NULL == cur_upd_res) ? 0 : cur_upd_res->d_total_full.rel_value_us);
970         }
971         else
972         {
973             GNUNET_asprintf (&data_upd_str, "%s;", data_upd_tmp);
974         }
975         GNUNET_free (data_upd_tmp);
976
977       }
978
979       //fprintf (stderr, "P: %u I: %u: P %i  A %i\n", c_peer, c_iteration, cur_res->peers, cur_res->addresses);
980       //fprintf (stderr, "D total: %llu\n", (long long unsigned int) cur_res->d_total.rel_value_us);
981
982       data_tmp = GNUNET_strdup (data_str);
983       GNUNET_free (data_str);
984       if (GNUNET_YES == cur_full_res->valid)
985       {
986           GNUNET_asprintf (&data_str, "%s;%llu", data_tmp,
987               cur_full_res->d_total_full.rel_value_us);
988       }
989       else
990       {
991           GNUNET_asprintf (&data_str, "%s;", data_tmp);
992       }
993
994       GNUNET_free (data_tmp);
995     }
996     data_tmp = GNUNET_strdup (data_str);
997     GNUNET_free (data_str);
998     GNUNET_asprintf (&data_str, "%s\n", data_tmp);
999     GNUNET_free (data_tmp);
1000
1001     fprintf (stderr, "Result full solution: %s\n", data_str);
1002     if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_full, data_str, strlen(data_str)))
1003       GNUNET_break (0);
1004     GNUNET_free (data_str);
1005
1006     if (ph.measure_updates)
1007     {
1008       data_upd_tmp = GNUNET_strdup (data_upd_str);
1009       GNUNET_free (data_upd_str);
1010       GNUNET_asprintf (&data_upd_str, "%s\n", data_upd_tmp);
1011       GNUNET_free (data_upd_tmp);
1012
1013       fprintf (stderr, "Result updated solution: `%s'\n", data_upd_str);
1014       if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data_upd_str, strlen(data_upd_str)))
1015         GNUNET_break (0);
1016       GNUNET_free (data_upd_str);
1017     }
1018   }
1019
1020   if ((NULL != f_full) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_full)))
1021     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
1022         data_fn_full);
1023   GNUNET_free_non_null (data_fn_full);
1024
1025   if ((NULL != f_update) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_update)))
1026     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
1027         data_fn_update);
1028   GNUNET_free_non_null (data_fn_update);
1029 }
1030
1031 /**
1032  * Run a performance iteration
1033  */
1034
1035 static void
1036 perf_run_iteration (void)
1037 {
1038   struct ATS_Address *cur;
1039   struct ATS_Address *next;
1040   int cp;
1041   int ca;
1042   int count_p = ph.N_peers_end;
1043   int count_a = ph.N_address;
1044   struct ATS_Address * cur_addr;
1045   uint32_t net;
1046
1047   ph.iterations_results[ph.current_iteration-1].results_array = GNUNET_malloc ((count_p + 1) * sizeof (struct Result *));
1048   if (ph.measure_updates)
1049     ph.iterations_results[ph.current_iteration-1].update_results_array = GNUNET_malloc ((count_p + 1) * sizeof (struct Result *));
1050   ph.peers = GNUNET_malloc ((count_p) * sizeof (struct PerfPeer));
1051   for (cp = 0; cp < count_p; cp++)
1052     perf_create_peer (cp);
1053   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1054       "Iteration %u of %u, added %u peers\n", ph.current_iteration, ph.total_iterations, cp);
1055
1056   for (cp = 0; cp < count_p; cp++)
1057   {
1058     fprintf (stderr,"%u..", cp);
1059     if (GNUNET_NO == ph.bulk_running)
1060     {
1061       ph.bulk_running = GNUNET_YES;
1062       ph.env.sf.s_bulk_start (ph.solver);
1063     }
1064     ph.current_p = cp + 1;
1065     for (ca = 0; ca < count_a; ca++)
1066     {
1067       cur_addr = perf_create_address (cp, ca);
1068       /* Add address */
1069
1070       /* Random network selection */
1071       //net = 1 + GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_ATS_NetworkTypeCount - 1);
1072       /* Random equally distributed network selection */
1073       net = 1 + (ca %  (GNUNET_ATS_NetworkTypeCount - 1));
1074       /* fprintf (stderr, "Network: %u `%s'\n",
1075        * mod_net , GNUNET_ATS_print_network_type(mod_net)); */
1076
1077       cur_addr->atsi = GNUNET_new (struct GNUNET_ATS_Information);
1078       cur_addr->atsi_count = 1;
1079       cur_addr->atsi[0].type = htonl (GNUNET_ATS_NETWORK_TYPE);
1080       cur_addr->atsi[0].value = htonl (net);
1081       ph.env.sf.s_add (ph.solver, cur_addr, net);
1082
1083       ph.current_a = ca + 1;
1084       perf_address_initial_update (ph.solver, ph.addresses, cur_addr);
1085       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1086           "Adding address for peer %u address %u in network %s\n", cp, ca,
1087           GNUNET_ATS_print_network_type(net));
1088     }
1089     /* Notify solver about request */
1090     ph.env.sf.s_get (ph.solver, &ph.peers[cp].id);
1091
1092     if (cp + 1 >= ph.N_peers_start)
1093     {
1094       /* Disable bulk to solve the problem */
1095       if (GNUNET_YES == ph.bulk_running)
1096       {
1097         ph.expecting_solution = GNUNET_YES;
1098         ph.bulk_running = GNUNET_NO;
1099         ph.env.sf.s_bulk_stop (ph.solver);
1100       }
1101       else
1102         GNUNET_break (0);
1103
1104       /* Problem is solved by the solver here due to unlocking */
1105       ph.expecting_solution = GNUNET_NO;
1106
1107       /* Update the problem */
1108       if ((0 < ph.opt_update_percent) && (GNUNET_YES == ph.measure_updates))
1109       {
1110         /* Update */
1111         GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1112             "Updating problem with %u peers and %u addresses\n", cp + 1, ca);
1113
1114         ph.expecting_solution = GNUNET_YES;
1115         ph.performed_update = GNUNET_YES;
1116         if (GNUNET_NO == ph.bulk_running)
1117         {
1118           ph.bulk_running = GNUNET_YES;
1119           ph.env.sf.s_bulk_start (ph.solver);
1120         }
1121         perf_update_all_addresses (cp + 1, ca, ph.opt_update_percent);
1122         ph.bulk_running = GNUNET_NO;
1123         ph.env.sf.s_bulk_stop (ph.solver);
1124         /* Problem is solved by the solver here due to unlocking */
1125         ph.performed_update = GNUNET_NO;
1126         ph.expecting_solution = GNUNET_NO;
1127       }
1128       GNUNET_assert (GNUNET_NO == ph.bulk_running);
1129     }
1130   }
1131   fprintf (stderr,"\n");
1132   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1133       "Done, cleaning up addresses\n");
1134   if (GNUNET_NO == ph.bulk_running)
1135   {
1136     ph.env.sf.s_bulk_start (ph.solver);
1137     ph.bulk_running = GNUNET_YES;
1138   }
1139
1140   for (cp = 0; cp < count_p; cp++)
1141   {
1142     for (cur = ph.peers[cp].head; cur != NULL ; cur = next)
1143     {
1144       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1145           "Deleting addresses for peer %u\n", cp);
1146       GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (ph.addresses,
1147           &ph.peers[cp].id, cur));
1148       ph.env.sf.s_del (ph.solver, cur, GNUNET_NO);
1149       next = cur->next;
1150       GNUNET_CONTAINER_DLL_remove(ph.peers[cp].head, ph.peers[cp].tail, cur);
1151       GNUNET_free_non_null (cur->atsi);
1152       GNUNET_free (cur);
1153     }
1154   }
1155
1156   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1157       "Iteration done\n");
1158   GNUNET_free(ph.peers);
1159 }
1160
1161
1162 static void
1163 run (void *cls, char * const *args, const char *cfgfile,
1164     const struct GNUNET_CONFIGURATION_Handle *cfg)
1165 {
1166   GNUNET_log_setup ("perf-ats-solver", "WARNING", NULL);
1167   char *sep;
1168   char *src_filename = GNUNET_strdup (__FILE__);
1169   char *test_filename = cls;
1170   char *solver;
1171   char *plugin;
1172   struct GNUNET_CONFIGURATION_Handle *solver_cfg;
1173   unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount];
1174   unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount];
1175   int c;
1176   int c2;
1177
1178   /* Extract test name */
1179   if (NULL == (sep  = (strstr (src_filename,".c"))))
1180   {
1181     GNUNET_free (src_filename);
1182     GNUNET_break (0);
1183     ret = 1;
1184     return ;
1185   }
1186   sep[0] = '\0';
1187
1188   if (NULL != (sep = strstr (test_filename, ".exe")))
1189     sep[0] = '\0';
1190
1191   if (NULL == (solver = strstr (test_filename, src_filename)))
1192   {
1193     GNUNET_free (src_filename);
1194     GNUNET_break (0);
1195     ret = 1;
1196     return ;
1197   }
1198   solver += strlen (src_filename) +1;
1199
1200   if (0 == strcmp(solver, "proportional"))
1201   {
1202     ph.ats_mode = MODE_PROPORTIONAL;
1203     ph.ats_string = "proportional";
1204   }
1205   else if (0 == strcmp(solver, "mlp"))
1206   {
1207     ph.ats_mode = MODE_MLP;
1208     ph.ats_string = "mlp";
1209   }
1210   else if ((0 == strcmp(solver, "ril")))
1211   {
1212     ph.ats_mode = MODE_RIL;
1213     ph.ats_string = "ril";
1214   }
1215   else
1216   {
1217     GNUNET_free (src_filename);
1218     GNUNET_break (0);
1219     ret = 1;
1220     return ;
1221   }
1222   GNUNET_free (src_filename);
1223
1224   /* Calculcate peers */
1225   if ((0 == ph.N_peers_start) && (0 == ph.N_peers_end))
1226   {
1227     ph.N_peers_start = DEFAULT_PEERS_START;
1228     ph.N_peers_end = DEFAULT_PEERS_END;
1229   }
1230   if (0 == ph.N_address)
1231     ph.N_address = DEFAULT_ADDRESSES;
1232
1233
1234   if (ph.N_peers_start != ph.N_peers_end)
1235     fprintf (stderr, "Benchmarking solver `%s' with %u to %u peers and %u addresses in %u iterations\n",
1236         ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address, ph.total_iterations);
1237   else
1238     fprintf (stderr, "Benchmarking solver `%s' with %u peers and %u addresses in %u iterations\n",
1239         ph.ats_string, ph.N_peers_end, ph.N_address, ph.total_iterations);
1240
1241   if (0 == ph.opt_update_percent)
1242     ph.opt_update_percent = DEFAULT_UPDATE_PERCENTAGE;
1243
1244   /* Load quotas */
1245   solver_cfg = GNUNET_CONFIGURATION_create();
1246   if ((NULL == solver_cfg) || (GNUNET_SYSERR == (GNUNET_CONFIGURATION_load ( solver_cfg, "perf_ats_solver.conf"))))
1247   {
1248     GNUNET_break(0);
1249     end_now (1);
1250     return;
1251   }
1252   if (GNUNET_ATS_NetworkTypeCount != load_quotas (solver_cfg,
1253       quotas_out, quotas_in, GNUNET_ATS_NetworkTypeCount))
1254   {
1255     GNUNET_break(0);
1256     end_now (1);
1257     return;
1258   }
1259
1260   /* Create array of DLL to store results for iterations */
1261   ph.iterations_results = GNUNET_malloc (sizeof (struct Iteration) * ph.total_iterations);
1262
1263   /* Load solver */
1264   ph.env.cfg = solver_cfg;
1265   ph.stat = GNUNET_STATISTICS_create ("ats", cfg);
1266   ph.env.stats = ph.stat;
1267   ph.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
1268   ph.env.addresses = ph.addresses;
1269   ph.env.bandwidth_changed_cb = bandwidth_changed_cb;
1270   ph.env.get_preferences = &get_preferences_cb;
1271   ph.env.get_property = &get_property_cb;
1272   ph.env.network_count = GNUNET_ATS_NetworkTypeCount;
1273   ph.env.info_cb = &solver_info_cb;
1274   ph.env.info_cb_cls = NULL;
1275
1276   int networks[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType;
1277   for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
1278   {
1279     ph.env.networks[c] = networks[c];
1280     ph.env.out_quota[c] = quotas_out[c];
1281     ph.env.in_quota[c] = quotas_in[c];
1282     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Loading network quotas: `%s' %llu %llu \n",
1283         GNUNET_ATS_print_network_type(ph.env.networks[c]),
1284         ph.env.out_quota[c],
1285         ph.env.in_quota[c]);
1286   }
1287   GAS_normalization_start (NULL, NULL, &normalized_property_changed_cb, NULL );
1288
1289   GNUNET_asprintf (&plugin, "libgnunet_plugin_ats_%s", ph.ats_string);
1290   GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initializing solver `%s'\n"), ph.ats_string);
1291   if  (NULL == (ph.solver = GNUNET_PLUGIN_load (plugin, &ph.env)))
1292   {
1293     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize solver `%s'!\n"), plugin);
1294     ret = 1;
1295     return;
1296   }
1297
1298   /* Do the benchmark */
1299   for (ph.current_iteration = 1; ph.current_iteration <= ph.total_iterations; ph.current_iteration++)
1300   {
1301     fprintf (stderr, "Iteration %u of %u starting\n", ph.current_iteration, ph.total_iterations);
1302     perf_run_iteration ();
1303     evaluate (ph.current_iteration);
1304     fprintf (stderr, "Iteration %u of %u done\n", ph.current_iteration, ph.total_iterations);
1305   }
1306   if (ph.create_datafile)
1307     write_all_iterations ();
1308
1309   /* Unload solver*/
1310   GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Unloading solver `%s'\n"), ph.ats_string);
1311   GNUNET_PLUGIN_unload (plugin, ph.solver);
1312   GNUNET_free (plugin);
1313   for (c = 0; c < ph.total_iterations; c++ )
1314   {
1315     for (c2 = ph.N_peers_start; c2 < ph.N_peers_end; c2++ )
1316     {
1317       if (0 == c2)
1318         continue;
1319       if (ph.measure_updates)
1320         GNUNET_free_non_null (ph.iterations_results[c].update_results_array[c2]);
1321       GNUNET_free (ph.iterations_results[c].results_array[c2]);
1322     }
1323     if (ph.measure_updates)
1324       GNUNET_free (ph.iterations_results[c].update_results_array);
1325     GNUNET_free(ph.iterations_results[c].results_array);
1326   }
1327   GNUNET_free (ph.iterations_results);
1328
1329   GNUNET_CONFIGURATION_destroy (solver_cfg);
1330   GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
1331   ph.solver = NULL;
1332 }
1333
1334 /**
1335  * Main function of the benchmark
1336  *
1337  * @param argc argument count
1338  * @param argv argument values
1339  */
1340 int
1341 main (int argc, char *argv[])
1342 {
1343   /* extract command line arguments */
1344   ph.opt_update_percent = 0;
1345   ph.N_peers_start = 0;
1346   ph.N_peers_end = 0;
1347   ph.N_address = 0;
1348   ph.ats_string = NULL;
1349   ph.create_datafile = GNUNET_NO;
1350   ph.measure_updates = GNUNET_NO;
1351   ph.total_iterations = 1;
1352
1353   static struct GNUNET_GETOPT_CommandLineOption options[] = {
1354       { 'a', "addresses", NULL,
1355           gettext_noop ("addresses to use"),
1356           1, &GNUNET_GETOPT_set_uint, &ph.N_address },
1357       { 's', "start", NULL,
1358           gettext_noop ("start with peer"),
1359           1, &GNUNET_GETOPT_set_uint, &ph.N_peers_start },
1360       { 'e', "end", NULL,
1361           gettext_noop ("end with peer"),
1362           1, &GNUNET_GETOPT_set_uint, &ph.N_peers_end },
1363       { 'i', "iterations", NULL,
1364           gettext_noop ("number of iterations used for averaging (default: 1)"),
1365           1, &GNUNET_GETOPT_set_uint, &ph.total_iterations },
1366       { 'p', "percentage", NULL,
1367           gettext_noop ("update a fix percentage of addresses"),
1368           1, &GNUNET_GETOPT_set_uint, &ph.opt_update_percent },
1369       { 'd', "data", NULL,
1370           gettext_noop ("create data file"),
1371           0, &GNUNET_GETOPT_set_one, &ph.create_datafile},
1372       { 'u', "update", NULL,
1373           gettext_noop ("measure updates"),
1374           0, &GNUNET_GETOPT_set_one, &ph.measure_updates},
1375       GNUNET_GETOPT_OPTION_END
1376   };
1377
1378   GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]);
1379   return ret;
1380 }
1381
1382 /* end of file perf_ats_solver.c */