diff options
author | Nathan S. Evans <evans@in.tum.de> | 2010-08-10 15:17:00 +0000 |
---|---|---|
committer | Nathan S. Evans <evans@in.tum.de> | 2010-08-10 15:17:00 +0000 |
commit | 49f3bd45e74b2723ef94f66ca5077e23c00685d5 (patch) | |
tree | d71009f020b61282c0f5fac1a8f3f4628538eea6 /src | |
parent | 71cc9ab8f420c4724987647c11d679084269bc5a (diff) | |
download | gnunet-49f3bd45e74b2723ef94f66ca5077e23c00685d5.tar.gz gnunet-49f3bd45e74b2723ef94f66ca5077e23c00685d5.zip |
add statistics iteration to testing_group, test case for same.
Diffstat (limited to 'src')
-rw-r--r-- | src/testing/Makefile.am | 1 | ||||
-rw-r--r-- | src/testing/test_testing_topology.c | 43 | ||||
-rw-r--r-- | src/testing/testing_group.c | 205 |
3 files changed, 229 insertions, 20 deletions
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am index fa56e1726..bd4495035 100644 --- a/src/testing/Makefile.am +++ b/src/testing/Makefile.am | |||
@@ -16,6 +16,7 @@ libgnunettesting_la_SOURCES = \ | |||
16 | testing_group.c | 16 | testing_group.c |
17 | libgnunettesting_la_LIBADD = $(XLIB) \ | 17 | libgnunettesting_la_LIBADD = $(XLIB) \ |
18 | $(top_builddir)/src/core/libgnunetcore.la \ | 18 | $(top_builddir)/src/core/libgnunetcore.la \ |
19 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
19 | $(top_builddir)/src/transport/libgnunettransport.la \ | 20 | $(top_builddir)/src/transport/libgnunettransport.la \ |
20 | -lm \ | 21 | -lm \ |
21 | $(top_builddir)/src/util/libgnunetutil.la | 22 | $(top_builddir)/src/util/libgnunetutil.la |
diff --git a/src/testing/test_testing_topology.c b/src/testing/test_testing_topology.c index f357862c5..3d03d7611 100644 --- a/src/testing/test_testing_topology.c +++ b/src/testing/test_testing_topology.c | |||
@@ -270,12 +270,40 @@ disconnect_cores (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) | |||
270 | total_server_connections -= 2; | 270 | total_server_connections -= 2; |
271 | } | 271 | } |
272 | 272 | ||
273 | void topology_cb (void *cls, | 273 | static void stats_finished (void *cls, int result) |
274 | const struct GNUNET_PeerIdentity *first, | 274 | { |
275 | const struct GNUNET_PeerIdentity *second, | 275 | fprintf(stderr, "Finished getting all peers statistics!\n"); |
276 | struct GNUNET_TIME_Relative latency, | 276 | GNUNET_SCHEDULER_add_now (sched, &finish_testing, NULL); |
277 | uint32_t distance, | 277 | } |
278 | const char *emsg) | 278 | |
279 | /** | ||
280 | * Callback function to process statistic values. | ||
281 | * | ||
282 | * @param cls closure | ||
283 | * @param peer the peer the statistics belong to | ||
284 | * @param subsystem name of subsystem that created the statistic | ||
285 | * @param name the name of the datum | ||
286 | * @param value the current value | ||
287 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
288 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
289 | */ | ||
290 | static int stats_print (void *cls, | ||
291 | const struct GNUNET_PeerIdentity *peer, | ||
292 | const char *subsystem, | ||
293 | const char *name, | ||
294 | uint64_t value, | ||
295 | int is_persistent) | ||
296 | { | ||
297 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s:%s:%s -- %llu\n", GNUNET_i2s(peer), subsystem, name, value); | ||
298 | return GNUNET_OK; | ||
299 | } | ||
300 | |||
301 | static void topology_cb (void *cls, | ||
302 | const struct GNUNET_PeerIdentity *first, | ||
303 | const struct GNUNET_PeerIdentity *second, | ||
304 | struct GNUNET_TIME_Relative latency, | ||
305 | uint32_t distance, | ||
306 | const char *emsg) | ||
279 | { | 307 | { |
280 | FILE *outfile; | 308 | FILE *outfile; |
281 | outfile = cls; | 309 | outfile = cls; |
@@ -295,7 +323,8 @@ void topology_cb (void *cls, | |||
295 | { | 323 | { |
296 | fprintf(outfile, "}\n"); | 324 | fprintf(outfile, "}\n"); |
297 | fclose(outfile); | 325 | fclose(outfile); |
298 | GNUNET_SCHEDULER_add_now (sched, &finish_testing, NULL); | 326 | GNUNET_TESTING_get_statistics(pg, &stats_finished, &stats_print, NULL); |
327 | //GNUNET_SCHEDULER_add_now (sched, &finish_testing, NULL); | ||
299 | } | 328 | } |
300 | } | 329 | } |
301 | } | 330 | } |
diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c index 2dace413a..df66720ef 100644 --- a/src/testing/testing_group.c +++ b/src/testing/testing_group.c | |||
@@ -333,9 +333,52 @@ struct TopologyIterateContext | |||
333 | unsigned int total; | 333 | unsigned int total; |
334 | }; | 334 | }; |
335 | 335 | ||
336 | struct TopologyCoreContext | 336 | struct StatsIterateContext |
337 | { | 337 | { |
338 | struct TopologyIterateContext *topology_context; | 338 | /** |
339 | * Handle to the statistics service. | ||
340 | */ | ||
341 | struct GNUNET_STATISTICS_Handle *stats_handle; | ||
342 | |||
343 | /** | ||
344 | * Handle for getting statistics. | ||
345 | */ | ||
346 | struct GNUNET_STATISTICS_GetHandle *stats_get_handle; | ||
347 | |||
348 | /** | ||
349 | * Continuation to call once all stats information has been retrieved. | ||
350 | */ | ||
351 | GNUNET_STATISTICS_Callback cont; | ||
352 | |||
353 | /** | ||
354 | * Proc function to call on each value received. | ||
355 | */ | ||
356 | GNUNET_TESTING_STATISTICS_Iterator proc; | ||
357 | |||
358 | /** | ||
359 | * Closure for topology_cb | ||
360 | */ | ||
361 | void *cls; | ||
362 | |||
363 | /** | ||
364 | * Number of peers currently connected to. | ||
365 | */ | ||
366 | unsigned int connected; | ||
367 | |||
368 | /** | ||
369 | * Number of peers we have finished iterating. | ||
370 | */ | ||
371 | unsigned int completed; | ||
372 | |||
373 | /** | ||
374 | * Number of peers total. | ||
375 | */ | ||
376 | unsigned int total; | ||
377 | }; | ||
378 | |||
379 | struct CoreContext | ||
380 | { | ||
381 | void *iter_context; | ||
339 | struct GNUNET_TESTING_Daemon *daemon; | 382 | struct GNUNET_TESTING_Daemon *daemon; |
340 | }; | 383 | }; |
341 | 384 | ||
@@ -2755,13 +2798,15 @@ internal_topology_callback(void *cls, | |||
2755 | const struct GNUNET_PeerIdentity *peer, | 2798 | const struct GNUNET_PeerIdentity *peer, |
2756 | struct GNUNET_TIME_Relative latency, uint32_t distance) | 2799 | struct GNUNET_TIME_Relative latency, uint32_t distance) |
2757 | { | 2800 | { |
2758 | struct TopologyCoreContext *core_ctx = cls; | 2801 | struct CoreContext *core_ctx = cls; |
2759 | struct TopologyIterateContext *iter_ctx = core_ctx->topology_context; | 2802 | struct TopologyIterateContext *iter_ctx = core_ctx->iter_context; |
2760 | 2803 | ||
2761 | if (peer == NULL) /* Either finished, or something went wrongo */ | 2804 | if (peer == NULL) /* Either finished, or something went wrong */ |
2762 | { | 2805 | { |
2763 | iter_ctx->completed++; | 2806 | iter_ctx->completed++; |
2764 | iter_ctx->connected--; | 2807 | iter_ctx->connected--; |
2808 | /* One core context allocated per iteration, must free! */ | ||
2809 | GNUNET_free(core_ctx); | ||
2765 | } | 2810 | } |
2766 | else | 2811 | else |
2767 | { | 2812 | { |
@@ -2771,8 +2816,8 @@ internal_topology_callback(void *cls, | |||
2771 | if (iter_ctx->completed == iter_ctx->total) | 2816 | if (iter_ctx->completed == iter_ctx->total) |
2772 | { | 2817 | { |
2773 | iter_ctx->topology_cb(iter_ctx->cls, NULL, NULL, GNUNET_TIME_relative_get_zero(), 0, NULL); | 2818 | iter_ctx->topology_cb(iter_ctx->cls, NULL, NULL, GNUNET_TIME_relative_get_zero(), 0, NULL); |
2819 | /* Once all are done, free the iteration context */ | ||
2774 | GNUNET_free(iter_ctx); | 2820 | GNUNET_free(iter_ctx); |
2775 | GNUNET_free(core_ctx); | ||
2776 | } | 2821 | } |
2777 | } | 2822 | } |
2778 | 2823 | ||
@@ -2784,12 +2829,12 @@ internal_topology_callback(void *cls, | |||
2784 | static void | 2829 | static void |
2785 | schedule_get_topology(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 2830 | schedule_get_topology(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
2786 | { | 2831 | { |
2787 | struct TopologyCoreContext *core_context = cls; | 2832 | struct CoreContext *core_context = cls; |
2788 | 2833 | struct TopologyIterateContext *topology_context = (struct TopologyIterateContext *)core_context->iter_context; | |
2789 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | 2834 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) |
2790 | return; | 2835 | return; |
2791 | 2836 | ||
2792 | if (core_context->topology_context->connected > MAX_OUTSTANDING_CONNECTIONS) | 2837 | if (topology_context->connected > MAX_OUTSTANDING_CONNECTIONS) |
2793 | { | 2838 | { |
2794 | #if VERBOSE_TESTING > 2 | 2839 | #if VERBOSE_TESTING > 2 |
2795 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2840 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -2803,7 +2848,7 @@ schedule_get_topology(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
2803 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2848 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2804 | _("Creating connection, outstanding_connections is %d\n"), outstanding_connects); | 2849 | _("Creating connection, outstanding_connections is %d\n"), outstanding_connects); |
2805 | #endif | 2850 | #endif |
2806 | core_context->topology_context->connected++; | 2851 | topology_context->connected++; |
2807 | if (GNUNET_OK != GNUNET_CORE_iterate_peers (core_context->daemon->sched, core_context->daemon->cfg, &internal_topology_callback, core_context)) | 2852 | if (GNUNET_OK != GNUNET_CORE_iterate_peers (core_context->daemon->sched, core_context->daemon->cfg, &internal_topology_callback, core_context)) |
2808 | internal_topology_callback(core_context, NULL, GNUNET_TIME_relative_get_zero(), 0); | 2853 | internal_topology_callback(core_context, NULL, GNUNET_TIME_relative_get_zero(), 0); |
2809 | 2854 | ||
@@ -2818,10 +2863,11 @@ void | |||
2818 | GNUNET_TESTING_get_topology (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_NotifyTopology cb, void *cls) | 2863 | GNUNET_TESTING_get_topology (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_NotifyTopology cb, void *cls) |
2819 | { | 2864 | { |
2820 | struct TopologyIterateContext *topology_context; | 2865 | struct TopologyIterateContext *topology_context; |
2821 | struct TopologyCoreContext *core_ctx; | 2866 | struct CoreContext *core_ctx; |
2822 | unsigned int i; | 2867 | unsigned int i; |
2823 | unsigned int total_count; | 2868 | unsigned int total_count; |
2824 | 2869 | ||
2870 | /* Allocate a single topology iteration context */ | ||
2825 | topology_context = GNUNET_malloc(sizeof(struct TopologyIterateContext)); | 2871 | topology_context = GNUNET_malloc(sizeof(struct TopologyIterateContext)); |
2826 | topology_context->topology_cb = cb; | 2872 | topology_context->topology_cb = cb; |
2827 | topology_context->cls = cls; | 2873 | topology_context->cls = cls; |
@@ -2830,9 +2876,11 @@ GNUNET_TESTING_get_topology (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING | |||
2830 | { | 2876 | { |
2831 | if (pg->peers[i].daemon->running == GNUNET_YES) | 2877 | if (pg->peers[i].daemon->running == GNUNET_YES) |
2832 | { | 2878 | { |
2833 | core_ctx = GNUNET_malloc(sizeof(struct TopologyCoreContext)); | 2879 | /* Allocate one core context per core we need to connect to */ |
2880 | core_ctx = GNUNET_malloc(sizeof(struct CoreContext)); | ||
2834 | core_ctx->daemon = pg->peers[i].daemon; | 2881 | core_ctx->daemon = pg->peers[i].daemon; |
2835 | core_ctx->topology_context = topology_context; | 2882 | /* Set back pointer to topology iteration context */ |
2883 | core_ctx->iter_context = topology_context; | ||
2836 | GNUNET_SCHEDULER_add_now(pg->sched, &schedule_get_topology, core_ctx); | 2884 | GNUNET_SCHEDULER_add_now(pg->sched, &schedule_get_topology, core_ctx); |
2837 | total_count++; | 2885 | total_count++; |
2838 | } | 2886 | } |
@@ -2842,6 +2890,137 @@ GNUNET_TESTING_get_topology (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING | |||
2842 | } | 2890 | } |
2843 | 2891 | ||
2844 | /** | 2892 | /** |
2893 | * Callback function to process statistic values. | ||
2894 | * This handler is here only really to insert a peer | ||
2895 | * identity (or daemon) so the statistics can be uniquely | ||
2896 | * tied to a single running peer. | ||
2897 | * | ||
2898 | * @param cls closure | ||
2899 | * @param subsystem name of subsystem that created the statistic | ||
2900 | * @param name the name of the datum | ||
2901 | * @param value the current value | ||
2902 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
2903 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
2904 | */ | ||
2905 | static int internal_stats_callback (void *cls, | ||
2906 | const char *subsystem, | ||
2907 | const char *name, | ||
2908 | uint64_t value, | ||
2909 | int is_persistent) | ||
2910 | { | ||
2911 | struct CoreContext *core_context = cls; | ||
2912 | struct StatsIterateContext *stats_context = (struct StatsIterateContext *)core_context->iter_context; | ||
2913 | |||
2914 | return stats_context->proc(stats_context->cls, &core_context->daemon->id, subsystem, name, value, is_persistent); | ||
2915 | } | ||
2916 | |||
2917 | /** | ||
2918 | * Internal continuation call for statistics iteration. | ||
2919 | * | ||
2920 | * @param cls closure, the CoreContext for this iteration | ||
2921 | * @param success whether or not the statistics iterations | ||
2922 | * was canceled or not (we don't care) | ||
2923 | */ | ||
2924 | static void internal_stats_cont (void *cls, int success) | ||
2925 | { | ||
2926 | struct CoreContext *core_context = cls; | ||
2927 | struct StatsIterateContext *stats_context = (struct StatsIterateContext *)core_context->iter_context; | ||
2928 | |||
2929 | stats_context->connected--; | ||
2930 | stats_context->completed++; | ||
2931 | |||
2932 | if (stats_context->completed == stats_context->total) | ||
2933 | { | ||
2934 | stats_context->cont(stats_context->cls, GNUNET_YES); | ||
2935 | if (stats_context->stats_handle != NULL) | ||
2936 | GNUNET_STATISTICS_destroy(stats_context->stats_handle, GNUNET_NO); | ||
2937 | GNUNET_free(stats_context); | ||
2938 | } | ||
2939 | GNUNET_free(core_context); | ||
2940 | } | ||
2941 | |||
2942 | /** | ||
2943 | * Check running topology iteration tasks, if below max start a new one, otherwise | ||
2944 | * schedule for some time in the future. | ||
2945 | */ | ||
2946 | static void | ||
2947 | schedule_get_statistics(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
2948 | { | ||
2949 | struct CoreContext *core_context = cls; | ||
2950 | struct StatsIterateContext *stats_context = (struct StatsIterateContext *)core_context->iter_context; | ||
2951 | |||
2952 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
2953 | return; | ||
2954 | |||
2955 | if (stats_context->connected > MAX_OUTSTANDING_CONNECTIONS) | ||
2956 | { | ||
2957 | #if VERBOSE_TESTING > 2 | ||
2958 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2959 | _("Delaying connect, we have too many outstanding connections!\n")); | ||
2960 | #endif | ||
2961 | GNUNET_SCHEDULER_add_delayed(core_context->daemon->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 100), &schedule_get_statistics, core_context); | ||
2962 | } | ||
2963 | else | ||
2964 | { | ||
2965 | #if VERBOSE_TESTING > 2 | ||
2966 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2967 | _("Creating connection, outstanding_connections is %d\n"), outstanding_connects); | ||
2968 | #endif | ||
2969 | |||
2970 | stats_context->connected++; | ||
2971 | stats_context->stats_handle = GNUNET_STATISTICS_create(core_context->daemon->sched, "testing", core_context->daemon->cfg); | ||
2972 | if (stats_context->stats_handle == NULL) | ||
2973 | { | ||
2974 | internal_stats_cont (core_context, GNUNET_NO); | ||
2975 | return; | ||
2976 | } | ||
2977 | |||
2978 | stats_context->stats_get_handle = GNUNET_STATISTICS_get(stats_context->stats_handle, NULL, NULL, GNUNET_TIME_relative_get_forever(), &internal_stats_cont, &internal_stats_callback, core_context); | ||
2979 | if (stats_context->stats_get_handle == NULL) | ||
2980 | internal_stats_cont (core_context, GNUNET_NO); | ||
2981 | |||
2982 | } | ||
2983 | } | ||
2984 | |||
2985 | |||
2986 | /** | ||
2987 | * Iterate over all (running) peers in the peer group, retrieve | ||
2988 | * all statistics from each. | ||
2989 | */ | ||
2990 | void | ||
2991 | GNUNET_TESTING_get_statistics (struct GNUNET_TESTING_PeerGroup *pg, | ||
2992 | GNUNET_STATISTICS_Callback cont, | ||
2993 | GNUNET_TESTING_STATISTICS_Iterator proc, void *cls) | ||
2994 | { | ||
2995 | struct StatsIterateContext *stats_context; | ||
2996 | struct CoreContext *core_ctx; | ||
2997 | unsigned int i; | ||
2998 | unsigned int total_count; | ||
2999 | |||
3000 | /* Allocate a single stats iteration context */ | ||
3001 | stats_context = GNUNET_malloc(sizeof(struct StatsIterateContext)); | ||
3002 | stats_context->cont = cont; | ||
3003 | stats_context->proc = proc; | ||
3004 | stats_context->cls = cls; | ||
3005 | total_count = 0; | ||
3006 | for (i = 0; i < pg->total; i++) | ||
3007 | { | ||
3008 | if (pg->peers[i].daemon->running == GNUNET_YES) | ||
3009 | { | ||
3010 | /* Allocate one core context per core we need to connect to */ | ||
3011 | core_ctx = GNUNET_malloc(sizeof(struct CoreContext)); | ||
3012 | core_ctx->daemon = pg->peers[i].daemon; | ||
3013 | /* Set back pointer to topology iteration context */ | ||
3014 | core_ctx->iter_context = stats_context; | ||
3015 | GNUNET_SCHEDULER_add_now(pg->sched, &schedule_get_statistics, core_ctx); | ||
3016 | total_count++; | ||
3017 | } | ||
3018 | } | ||
3019 | stats_context->total = total_count; | ||
3020 | return; | ||
3021 | } | ||
3022 | |||
3023 | /** | ||
2845 | * There are many ways to connect peers that are supported by this function. | 3024 | * There are many ways to connect peers that are supported by this function. |
2846 | * To connect peers in the same topology that was created via the | 3025 | * To connect peers in the same topology that was created via the |
2847 | * GNUNET_TESTING_create_topology, the topology variable must be set to | 3026 | * GNUNET_TESTING_create_topology, the topology variable must be set to |