aboutsummaryrefslogtreecommitdiff
path: root/src/testbed
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-03-13 10:51:45 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-03-13 10:51:45 +0000
commit0043aada3f5172d461f89eecc9138b6a1754ca14 (patch)
tree6970bdc8d0acf430db3b6dee674149a2aeb9273a /src/testbed
parente27e2a35da519f85d7597890557f83a4d432e414 (diff)
downloadgnunet-0043aada3f5172d461f89eecc9138b6a1754ca14.tar.gz
gnunet-0043aada3f5172d461f89eecc9138b6a1754ca14.zip
Implement GNUNET_TESTBED_get_statistics() - resolves #2662
Test case for testing GNUNET_TESTBED_get_statistics() Fix waiting for SHUTDOWN_PEERS reply when controller crashes
Diffstat (limited to 'src/testbed')
-rw-r--r--src/testbed/Makefile.am10
-rw-r--r--src/testbed/test_testbed_api_statistics.conf93
-rw-r--r--src/testbed/testbed_api.c4
-rw-r--r--src/testbed/testbed_api_operations.c17
-rw-r--r--src/testbed/testbed_api_operations.h11
-rw-r--r--src/testbed/testbed_api_statistics.c341
-rw-r--r--src/testbed/testbed_api_testbed.c23
7 files changed, 481 insertions, 18 deletions
diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am
index 2189de3cb..bc703ebcb 100644
--- a/src/testbed/Makefile.am
+++ b/src/testbed/Makefile.am
@@ -120,7 +120,8 @@ check_PROGRAMS = \
120 test_testbed_api_testbed_run_topology2dtorus \ 120 test_testbed_api_testbed_run_topology2dtorus \
121 test_testbed_api_testbed_run_topologysmallworld \ 121 test_testbed_api_testbed_run_topologysmallworld \
122 test_testbed_api_testbed_run_topologyfromfile \ 122 test_testbed_api_testbed_run_topologyfromfile \
123 test_testbed_api_testbed_run_topologyscalefree 123 test_testbed_api_testbed_run_topologyscalefree \
124 test_testbed_api_statistics
124 125
125if ENABLE_TEST_RUN 126if ENABLE_TEST_RUN
126 TESTS = \ 127 TESTS = \
@@ -134,6 +135,7 @@ if ENABLE_TEST_RUN
134 test_testbed_api_3peers_3controllers \ 135 test_testbed_api_3peers_3controllers \
135 test_testbed_api_testbed_run \ 136 test_testbed_api_testbed_run \
136 test_testbed_api_test \ 137 test_testbed_api_test \
138 test_testbed_api_statistics \
137 test_testbed_api_topology \ 139 test_testbed_api_topology \
138 test_testbed_api_topology_clique \ 140 test_testbed_api_topology_clique \
139 test_testbed_api_testbed_run_topologyrandom \ 141 test_testbed_api_testbed_run_topologyrandom \
@@ -278,6 +280,12 @@ test_testbed_api_testbed_run_topologyscalefree_LDADD = \
278 $(top_builddir)/src/util/libgnunetutil.la \ 280 $(top_builddir)/src/util/libgnunetutil.la \
279 libgnunettestbed.la 281 libgnunettestbed.la
280 282
283test_testbed_api_statistics_SOURCES = \
284 test_testbed_api_statistics.c
285test_testbed_api_statistics_LDADD = \
286 $(top_builddir)/src/util/libgnunetutil.la \
287 libgnunettestbed.la
288
281EXTRA_DIST = \ 289EXTRA_DIST = \
282 test_testbed_api.conf \ 290 test_testbed_api.conf \
283 test_testbed_api_testbed_run_topologyring.conf \ 291 test_testbed_api_testbed_run_topologyring.conf \
diff --git a/src/testbed/test_testbed_api_statistics.conf b/src/testbed/test_testbed_api_statistics.conf
new file mode 100644
index 000000000..36de44147
--- /dev/null
+++ b/src/testbed/test_testbed_api_statistics.conf
@@ -0,0 +1,93 @@
1[testbed]
2AUTOSTART = NO
3PORT = 12113
4ACCEPT_FROM = 127.0.0.1;
5HOSTNAME = localhost
6NEIGHBOUR_LIMIT = 100
7OVERLAY_TOPOLOGY = 2D_TORUS
8#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args
9
10[fs]
11AUTOSTART = NO
12
13[resolver]
14AUTOSTART = NO
15
16[mesh]
17AUTOSTART = NO
18
19[dht]
20AUTOSTART = NO
21
22[block]
23plugins = dht test
24
25[dhtcache]
26QUOTA = 1 MB
27DATABASE = sqlite
28
29[transport]
30PLUGINS = tcp
31ACCEPT_FROM6 = ::1;
32ACCEPT_FROM = 127.0.0.1;
33NEIGHBOUR_LIMIT = 50
34PORT = 12365
35
36[ats]
37WAN_QUOTA_OUT = 3932160
38WAN_QUOTA_IN = 3932160
39
40[core]
41PORT = 12092
42AUTOSTART = YES
43USE_EPHEMERAL_KEYS = NO
44
45[arm]
46DEFAULTSERVICES = core transport
47PORT = 12366
48
49[transport-tcp]
50TIMEOUT = 300 s
51PORT = 12368
52
53[TESTING]
54NUM_PEERS = 5
55WEAKRANDOM = YES
56HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat
57MAX_CONCURRENT_SSH = 10
58USE_PROGRESSBARS = YES
59PEERGROUP_TIMEOUT = 2400 s
60
61[gnunetd]
62HOSTKEY = $SERVICEHOME/.hostkey
63
64[PATHS]
65SERVICEHOME = /tmp/test-testbed/
66
67[dns]
68AUTOSTART = NO
69
70[nse]
71AUTOSTART = NO
72
73[vpn]
74AUTOSTART = NO
75
76[nat]
77RETURN_LOCAL_ADDRESSES = YES
78
79[gns-helper-service-w32]
80AUTOSTART = NO
81
82[consensus]
83AUTOSTART = NO
84
85[gns]
86AUTOSTART = NO
87
88[statistics]
89AUTOSTART = YES
90PORT = 30
91
92[peerinfo]
93NO_IO = YES
diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c
index 0c891b447..117b39833 100644
--- a/src/testbed/testbed_api.c
+++ b/src/testbed/testbed_api.c
@@ -47,13 +47,13 @@
47 * Generic logging shorthand 47 * Generic logging shorthand
48 */ 48 */
49#define LOG(kind, ...) \ 49#define LOG(kind, ...) \
50 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__); 50 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__)
51 51
52/** 52/**
53 * Debug logging 53 * Debug logging
54 */ 54 */
55#define LOG_DEBUG(...) \ 55#define LOG_DEBUG(...) \
56 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__); 56 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
57 57
58/** 58/**
59 * Relative time seconds shorthand 59 * Relative time seconds shorthand
diff --git a/src/testbed/testbed_api_operations.c b/src/testbed/testbed_api_operations.c
index 3e7eb91bd..d213d3334 100644
--- a/src/testbed/testbed_api_operations.c
+++ b/src/testbed/testbed_api_operations.c
@@ -280,6 +280,23 @@ GNUNET_TESTBED_operation_queue_destroy_ (struct OperationQueue *queue)
280 280
281 281
282/** 282/**
283 * Destroys the operation queue if it is empty. If not empty return GNUNET_NO.
284 *
285 * @param queue the queue to destroy if empty
286 * @return GNUNET_YES if the queue is destroyed. GNUNET_NO if not (because it
287 * is not empty)
288 */
289int
290GNUNET_TESTBED_operation_queue_destroy_empty_ (struct OperationQueue *q)
291{
292 if (NULL != q->head)
293 return GNUNET_NO;
294 GNUNET_TESTBED_operation_queue_destroy_ (q);
295 return GNUNET_YES;
296}
297
298
299/**
283 * Function to reset the maximum number of operations in the given queue. If 300 * Function to reset the maximum number of operations in the given queue. If
284 * max_active is lesser than the number of currently active operations, the 301 * max_active is lesser than the number of currently active operations, the
285 * active operations are not stopped immediately. 302 * active operations are not stopped immediately.
diff --git a/src/testbed/testbed_api_operations.h b/src/testbed/testbed_api_operations.h
index 61b45e236..403dd889c 100644
--- a/src/testbed/testbed_api_operations.h
+++ b/src/testbed/testbed_api_operations.h
@@ -59,6 +59,17 @@ GNUNET_TESTBED_operation_queue_destroy_ (struct OperationQueue *queue);
59 59
60 60
61/** 61/**
62 * Destroys the operation queue if it is empty. If not empty return GNUNET_NO.
63 *
64 * @param queue the queue to destroy if empty
65 * @return GNUNET_YES if the queue is destroyed. GNUNET_NO if not (because it
66 * is not empty)
67 */
68int
69GNUNET_TESTBED_operation_queue_destroy_empty_ (struct OperationQueue *q);
70
71
72/**
62 * Function to reset the maximum number of operations in the given queue. If 73 * Function to reset the maximum number of operations in the given queue. If
63 * max_active is lesser than the number of currently active operations, the 74 * max_active is lesser than the number of currently active operations, the
64 * active operations are not stopped immediately. 75 * active operations are not stopped immediately.
diff --git a/src/testbed/testbed_api_statistics.c b/src/testbed/testbed_api_statistics.c
index f013c0302..d6af1bce2 100644
--- a/src/testbed/testbed_api_statistics.c
+++ b/src/testbed/testbed_api_statistics.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 (C) 2008--2012 Christian Grothoff (and other contributing authors) 3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -25,8 +25,324 @@
25 * @author Sree Harsha Totakura 25 * @author Sree Harsha Totakura
26 */ 26 */
27#include "platform.h" 27#include "platform.h"
28#include "gnunet_common.h"
28#include "gnunet_testbed_service.h" 29#include "gnunet_testbed_service.h"
29 30
31#include "testbed_api_operations.h"
32
33
34/**
35 * Generic logging shorthand
36 */
37#define LOG(kind,...) \
38 GNUNET_log_from (kind, "testbed-api-statistics", __VA_ARGS__)
39
40/**
41 * Debug logging shorthand
42 */
43#define LOG_DEBUG(...) \
44 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
45
46
47/**
48 * Context information for use in GNUNET_TESTBED_get_statistics()
49 */
50struct GetStatsContext
51{
52 /**
53 * The main operation we generate while creating this context
54 */
55 struct GNUNET_TESTBED_Operation *main_op;
56
57 /**
58 * The service connect operations we create to open connection to the
59 * statistics service of each given peer
60 */
61 struct GNUNET_TESTBED_Operation **ops;
62
63 /**
64 * The array of peers whose statistics services are to be accessed
65 */
66 struct GNUNET_TESTBED_Peer **peers;
67
68 /**
69 * The iterator to call with statistics information
70 */
71 GNUNET_TESTBED_StatisticsIterator proc;
72
73 /**
74 * The callback to call when we are done iterating through all peers'
75 * statistics services
76 */
77 GNUNET_TESTBED_OperationCompletionCallback cont;
78
79 /**
80 * The closure for the above callbacks
81 */
82 void *cb_cls;
83
84 /**
85 * The task for calling the continuation callback
86 */
87 GNUNET_SCHEDULER_TaskIdentifier call_completion_task_id;
88
89 /**
90 * The number of peers present in the peers array. This number also
91 * represents the number of service connect operations in the ops array
92 */
93 unsigned int num_peers;
94
95 /**
96 * How many peers' statistics have we iterated through
97 */
98 unsigned int num_completed;
99
100};
101
102
103/**
104 * Context information with respect to a particular peer
105 */
106struct PeerGetStatsContext
107{
108 /**
109 * The GetStatsContext which is associated with this context
110 */
111 struct GetStatsContext *sc;
112
113 /**
114 * The handle from GNUNET_STATISTICS_get()
115 */
116 struct GNUNET_STATISTICS_GetHandle *get_handle;
117
118 /**
119 * The index of this peer in the peers array of GetStatsContext
120 */
121 unsigned int peer_index;
122};
123
124
125/**
126 * A no-wait operation queue
127 */
128static struct OperationQueue *no_wait_queue;
129
130
131/**
132 * Call statistics operation completion. We call it in a separate task because
133 * the iteration_completion_cb() cannot destroy statistics handle which will be
134 * the case if the user calles GNUNET_TESTBED_operation_done() on the
135 * get_statistics operation.
136 *
137 * @param cls the GetStatsContext
138 * @param tc the scheduler task context
139 */
140static void
141call_completion_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
142{
143 struct GetStatsContext *sc = cls;
144
145 GNUNET_assert (sc->call_completion_task_id != GNUNET_SCHEDULER_NO_TASK);
146 sc->call_completion_task_id = GNUNET_SCHEDULER_NO_TASK;
147 LOG_DEBUG ("Calling get_statistics() continuation callback\n");
148 sc->cont (sc->cb_cls, sc->main_op, NULL);
149}
150
151
152/**
153 * Continuation called by the "get_all" and "get" functions.
154 *
155 * @param cls the PeerGetStatsContext
156 * @param success GNUNET_OK if statistics were
157 * successfully obtained, GNUNET_SYSERR if not.
158 */
159static void
160iteration_completion_cb (void *cls, int success)
161{
162 struct PeerGetStatsContext *peer_sc = cls;
163 struct GetStatsContext *sc;
164
165 if (NULL == peer_sc->get_handle)
166 {
167 /* We are being called after we cancelled the GetHandle */
168 GNUNET_assert (GNUNET_SYSERR == success);
169 return;
170 }
171 GNUNET_break (GNUNET_OK == success);
172 sc = peer_sc->sc;
173 peer_sc->get_handle = NULL;
174 sc->num_completed++;
175 if (sc->num_completed == sc->num_peers)
176 {
177 LOG_DEBUG ("Scheduling to call iteration completion callback\n");
178 sc->call_completion_task_id =
179 GNUNET_SCHEDULER_add_now (&call_completion_task, sc);
180 }
181}
182
183
184/**
185 * Callback function to process statistic values.
186 *
187 * @param cls the PeerGetStatsContext
188 * @param subsystem name of subsystem that created the statistic
189 * @param name the name of the datum
190 * @param value the current value
191 * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
192 * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
193 */
194static int
195iterator_cb (void *cls, const char *subsystem,
196 const char *name, uint64_t value,
197 int is_persistent)
198{
199 struct PeerGetStatsContext *peer_sc = cls;
200 struct GetStatsContext *sc;
201 struct GNUNET_TESTBED_Peer *peer;
202 int ret;
203
204 sc = peer_sc->sc;
205 peer = sc->peers[peer_sc->peer_index];
206 LOG_DEBUG ("Peer %u: [%s,%s] -> %lu\n", peer_sc->peer_index,
207 subsystem, name, (unsigned long) value);
208 ret = sc->proc (sc->cb_cls, peer,
209 subsystem, name, value, is_persistent);
210 if (GNUNET_SYSERR == ret)
211 LOG_DEBUG ("Aborting iteration for peer %u\n", peer_sc->peer_index);
212 return ret;
213}
214
215
216/**
217 * Called after opening a connection to the statistics service of a peer
218 *
219 * @param cls the PeerGetStatsContext
220 * @param op the operation that has been finished
221 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
222 * @param emsg error message in case the operation has failed; will be NULL if
223 * operation has executed successfully.
224 */
225static void
226service_connect_comp (void *cls,
227 struct GNUNET_TESTBED_Operation *op,
228 void *ca_result,
229 const char *emsg)
230{
231 struct PeerGetStatsContext *peer_sc = cls;
232 struct GNUNET_STATISTICS_Handle *h = ca_result;
233
234 LOG_DEBUG ("Retrieving statistics of peer %u\n", peer_sc->peer_index);
235 peer_sc->get_handle =
236 GNUNET_STATISTICS_get (h, NULL, NULL,
237 GNUNET_TIME_UNIT_FOREVER_REL,
238 &iteration_completion_cb,
239 iterator_cb, peer_sc);
240}
241
242
243/**
244 * Adapter function called to establish a connection to the statistics service
245 * of a peer.
246 *
247 * @param cls the PeerGetStatsContext
248 * @param cfg configuration of the peer to connect to; will be available until
249 * GNUNET_TESTBED_operation_done() is called on the operation returned
250 * from GNUNET_TESTBED_service_connect()
251 * @return service handle to return in 'op_result', NULL on error
252 */
253static void *
254statistics_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
255{
256 struct PeerGetStatsContext *peer_sc = cls;
257
258 LOG_DEBUG ("Connecting to statistics service of peer %u\n",
259 peer_sc->peer_index);
260 return GNUNET_STATISTICS_create ("<testbed-api>", cfg);
261}
262
263
264/**
265 * Adapter function called to destroy statistics connection
266 *
267 * @param cls the PeerGetStatsContext
268 * @param op_result service handle returned from the connect adapter
269 */
270static void
271statistics_da (void *cls, void *op_result)
272{
273 struct PeerGetStatsContext *peer_sc = cls;
274
275 if (NULL != peer_sc->get_handle)
276 {
277 GNUNET_STATISTICS_get_cancel (peer_sc->get_handle);
278 peer_sc->get_handle = NULL;
279 }
280 GNUNET_STATISTICS_destroy ((struct GNUNET_STATISTICS_Handle *) op_result,
281 GNUNET_NO);
282 GNUNET_free (peer_sc);
283}
284
285
286/**
287 * Function called when get_statistics operation is ready
288 *
289 * @param cls the GetStatsContext
290 */
291static void
292opstart_get_stats (void *cls)
293{
294 struct GetStatsContext *sc = cls;
295 struct PeerGetStatsContext *peer_sc;
296 unsigned int peer;
297
298 LOG_DEBUG ("Starting get_statistics operation\n");
299 sc->ops = GNUNET_malloc (sc->num_peers *
300 sizeof (struct GNUNET_TESTBED_Operation *));
301 for (peer = 0; peer < sc->num_peers; peer++)
302 {
303 peer_sc = GNUNET_malloc (sizeof (struct PeerGetStatsContext));
304 peer_sc->sc = sc;
305 peer_sc->peer_index = peer;
306 sc->ops[peer] =
307 GNUNET_TESTBED_service_connect (sc, sc->peers[peer], "statistics",
308 &service_connect_comp,
309 peer_sc,
310 &statistics_ca,
311 &statistics_da,
312 peer_sc);
313 }
314}
315
316
317/**
318 * Function called when get_statistics operation is cancelled or marked as done
319 *
320 * @param cls the GetStatsContext
321 */
322static void
323oprelease_get_stats (void *cls)
324{
325 struct GetStatsContext *sc = cls;
326 unsigned int peer;
327
328 LOG_DEBUG ("Cleaning up get_statistics operation\n");
329 if (GNUNET_SCHEDULER_NO_TASK != sc->call_completion_task_id)
330 GNUNET_SCHEDULER_cancel (sc->call_completion_task_id);
331 if (NULL != sc->ops)
332 {
333 for (peer = 0; peer < sc->num_peers; peer++)
334 {
335 if (NULL != sc->ops[peer])
336 GNUNET_TESTBED_operation_done (sc->ops[peer]);
337 }
338 GNUNET_free (sc->ops);
339 }
340 GNUNET_free (sc);
341 if (GNUNET_YES ==
342 GNUNET_TESTBED_operation_queue_destroy_empty_ (no_wait_queue))
343 no_wait_queue = NULL;
344}
345
30 346
31/** 347/**
32 * Convenience method that iterates over all (running) peers 348 * Convenience method that iterates over all (running) peers
@@ -46,10 +362,25 @@ GNUNET_TESTBED_get_statistics (unsigned int num_peers,
46 GNUNET_TESTBED_OperationCompletionCallback cont, 362 GNUNET_TESTBED_OperationCompletionCallback cont,
47 void *cls) 363 void *cls)
48{ 364{
49 // FIXME: not implemented, but clients will kind-of work if we do this: 365 struct GetStatsContext *sc;
50 GNUNET_break (0); 366
51 cont (cls, NULL, "not implemented"); 367 GNUNET_assert (NULL != proc);
52 return NULL; 368 GNUNET_assert (NULL != cont);
369 if (NULL == no_wait_queue)
370 no_wait_queue =
371 GNUNET_TESTBED_operation_queue_create_ (UINT_MAX);
372 sc = GNUNET_malloc (sizeof (struct GetStatsContext));
373 sc->peers = peers;
374 sc->proc = proc;
375 sc->cont = cont;
376 sc->cb_cls = cls;
377 sc->num_peers = num_peers;
378 sc->main_op =
379 GNUNET_TESTBED_operation_create_ (sc, &opstart_get_stats,
380 &oprelease_get_stats);
381 GNUNET_TESTBED_operation_queue_insert_ (no_wait_queue, sc->main_op);
382 GNUNET_TESTBED_operation_begin_wait_ (sc->main_op);
383 return sc->main_op;
53} 384}
54 385
55 386
diff --git a/src/testbed/testbed_api_testbed.c b/src/testbed/testbed_api_testbed.c
index 24ca2653c..3bd6f1db8 100644
--- a/src/testbed/testbed_api_testbed.c
+++ b/src/testbed/testbed_api_testbed.c
@@ -800,18 +800,21 @@ controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
800 800
801 if (status != GNUNET_OK) 801 if (status != GNUNET_OK)
802 { 802 {
803 switch (rc->state) 803 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
804 {
805 case RC_INIT:
806 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Testbed startup failed\n");
807 return;
808 default:
809 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
810 "Controller crash detected. Shutting down.\n"); 804 "Controller crash detected. Shutting down.\n");
811 rc->cproc = NULL; 805 rc->cproc = NULL;
812 shutdown_now (rc); 806 if (NULL != rc->peers)
813 return; 807 {
808 GNUNET_free (rc->peers);
809 rc->peers = NULL;
810 }
811 if (NULL != rc->c)
812 {
813 GNUNET_TESTBED_controller_disconnect (rc->c);
814 rc->c = NULL;
814 } 815 }
816 shutdown_now (rc);
817 return;
815 } 818 }
816 GNUNET_CONFIGURATION_destroy (rc->cfg); 819 GNUNET_CONFIGURATION_destroy (rc->cfg);
817 rc->cfg = GNUNET_CONFIGURATION_dup (cfg); 820 rc->cfg = GNUNET_CONFIGURATION_dup (cfg);