diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-09-10 12:18:07 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-09-10 12:18:07 +0000 |
commit | 9363d5db9dd612c1ec8be0f202da23aeaf09be49 (patch) | |
tree | c10ade1161826fdadd24f1e1a2e350596f4a0a19 /src | |
parent | abe521f93a227ef120cd75c7d649782951e8eca5 (diff) | |
download | gnunet-9363d5db9dd612c1ec8be0f202da23aeaf09be49.tar.gz gnunet-9363d5db9dd612c1ec8be0f202da23aeaf09be49.zip |
- experiment driver propagates barrier crossed notification
Diffstat (limited to 'src')
-rw-r--r-- | src/testbed/gnunet-service-testbed.c | 2 | ||||
-rw-r--r-- | src/testbed/gnunet-service-testbed_barriers.c | 143 | ||||
-rw-r--r-- | src/testbed/gnunet-service-testbed_barriers.h | 14 | ||||
-rw-r--r-- | src/testbed/testbed_api_barriers.c | 43 | ||||
-rw-r--r-- | src/testbed/testbed_api_barriers.h | 52 |
5 files changed, 204 insertions, 50 deletions
diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c index 0373f4196..7d66b6fec 100644 --- a/src/testbed/gnunet-service-testbed.c +++ b/src/testbed/gnunet-service-testbed.c | |||
@@ -903,6 +903,8 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
903 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT, 0}, | 903 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT, 0}, |
904 | {&GST_handle_barrier_cancel, NULL, | 904 | {&GST_handle_barrier_cancel, NULL, |
905 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL, 0}, | 905 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL, 0}, |
906 | {&GST_handle_barrier_status, NULL, | ||
907 | GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, 0}, | ||
906 | {NULL, NULL, 0, 0} | 908 | {NULL, NULL, 0, 0} |
907 | }; | 909 | }; |
908 | char *logfile; | 910 | char *logfile; |
diff --git a/src/testbed/gnunet-service-testbed_barriers.c b/src/testbed/gnunet-service-testbed_barriers.c index 663c090b6..68011065d 100644 --- a/src/testbed/gnunet-service-testbed_barriers.c +++ b/src/testbed/gnunet-service-testbed_barriers.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include "gnunet-service-testbed.h" | 27 | #include "gnunet-service-testbed.h" |
28 | #include "gnunet-service-testbed_barriers.h" | 28 | #include "gnunet-service-testbed_barriers.h" |
29 | #include "testbed_api_barriers.h" | ||
29 | 30 | ||
30 | 31 | ||
31 | /** | 32 | /** |
@@ -328,7 +329,8 @@ cleanup_clientctx (struct ClientCtx *ctx) | |||
328 | { | 329 | { |
329 | struct MessageQueue *mq; | 330 | struct MessageQueue *mq; |
330 | 331 | ||
331 | GNUNET_SERVER_client_drop (ctx->client); | 332 | if (NULL != ctx->client) |
333 | GNUNET_SERVER_client_drop (ctx->client); | ||
332 | if (NULL != ctx->tx) | 334 | if (NULL != ctx->tx) |
333 | GNUNET_SERVER_notify_transmit_ready_cancel (ctx->tx); | 335 | GNUNET_SERVER_notify_transmit_ready_cancel (ctx->tx); |
334 | if (NULL != (mq = ctx->mq_head)) | 336 | if (NULL != (mq = ctx->mq_head)) |
@@ -358,7 +360,13 @@ remove_barrier (struct Barrier *barrier) | |||
358 | while (NULL != (ctx = barrier->head)) | 360 | while (NULL != (ctx = barrier->head)) |
359 | { | 361 | { |
360 | GNUNET_CONTAINER_DLL_remove (barrier->head, barrier->tail, ctx); | 362 | GNUNET_CONTAINER_DLL_remove (barrier->head, barrier->tail, ctx); |
361 | cleanup_clientctx (ctx); | 363 | GNUNET_SERVER_client_drop (ctx->client); |
364 | ctx->client = NULL; | ||
365 | if (NULL != ctx->tx) | ||
366 | { | ||
367 | GNUNET_SERVER_notify_transmit_ready_cancel (ctx->tx); | ||
368 | ctx->tx = NULL; | ||
369 | } | ||
362 | } | 370 | } |
363 | GNUNET_free (barrier->name); | 371 | GNUNET_free (barrier->name); |
364 | GNUNET_SERVER_client_drop (barrier->mc); | 372 | GNUNET_SERVER_client_drop (barrier->mc); |
@@ -436,41 +444,6 @@ send_barrier_status_msg (struct Barrier *barrier, const char *emsg) | |||
436 | } | 444 | } |
437 | 445 | ||
438 | 446 | ||
439 | |||
440 | /** | ||
441 | * Task for sending barrier crossed notifications to waiting client | ||
442 | * | ||
443 | * @param cls the barrier which is crossed | ||
444 | * @param tc scheduler task context | ||
445 | */ | ||
446 | static void | ||
447 | notify_task_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
448 | { | ||
449 | struct Barrier *barrier = cls; | ||
450 | struct ClientCtx *client_ctx; | ||
451 | struct GNUNET_TESTBED_BarrierStatusMsg *msg; | ||
452 | struct GNUNET_MessageHeader *dup_msg; | ||
453 | uint16_t name_len; | ||
454 | uint16_t msize; | ||
455 | |||
456 | name_len = strlen (barrier->name) + 1; | ||
457 | msize = sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len; | ||
458 | msg = GNUNET_malloc (msize); | ||
459 | msg->header.size = htons (msize); | ||
460 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS); | ||
461 | msg->status = htons (BARRIER_STATUS_CROSSED); | ||
462 | msg->name_len = htons (name_len); | ||
463 | (void) memcpy (msg->data, barrier->name, name_len); | ||
464 | msg->data[name_len] = '\0'; | ||
465 | while (NULL != (client_ctx = barrier->head)) | ||
466 | { | ||
467 | dup_msg = GNUNET_copy_message (&msg->header); | ||
468 | queue_message (client_ctx, dup_msg); | ||
469 | GNUNET_CONTAINER_DLL_remove (barrier->head, barrier->tail, client_ctx); | ||
470 | } | ||
471 | } | ||
472 | |||
473 | |||
474 | /** | 447 | /** |
475 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT messages. This | 448 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT messages. This |
476 | * message should come from peers or a shared helper service using the | 449 | * message should come from peers or a shared helper service using the |
@@ -538,7 +511,6 @@ handle_barrier_wait (void *cls, struct GNUNET_SERVER_Client *client, | |||
538 | { | 511 | { |
539 | barrier->status = BARRIER_STATUS_CROSSED; | 512 | barrier->status = BARRIER_STATUS_CROSSED; |
540 | send_barrier_status_msg (barrier, NULL); | 513 | send_barrier_status_msg (barrier, NULL); |
541 | notify_task_cb (barrier, NULL); | ||
542 | } | 514 | } |
543 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 515 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
544 | } | 516 | } |
@@ -560,9 +532,6 @@ disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client) | |||
560 | if (NULL == client) | 532 | if (NULL == client) |
561 | return; | 533 | return; |
562 | client_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientCtx); | 534 | client_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientCtx); |
563 | if (NULL == client_ctx) | ||
564 | return; /* We only set user context for locally | ||
565 | connected clients */ | ||
566 | cleanup_clientctx (client_ctx); | 535 | cleanup_clientctx (client_ctx); |
567 | } | 536 | } |
568 | 537 | ||
@@ -777,11 +746,12 @@ GST_handle_barrier_init (void *cls, struct GNUNET_SERVER_Client *client, | |||
777 | wrapper = GNUNET_malloc (sizeof (struct WBarrier)); | 746 | wrapper = GNUNET_malloc (sizeof (struct WBarrier)); |
778 | wrapper->barrier = barrier; | 747 | wrapper->barrier = barrier; |
779 | GNUNET_CONTAINER_DLL_insert_tail (barrier->whead, barrier->wtail, wrapper); | 748 | GNUNET_CONTAINER_DLL_insert_tail (barrier->whead, barrier->wtail, wrapper); |
780 | wrapper->hbarrier = GNUNET_TESTBED_barrier_init (slave->controller, | 749 | wrapper->hbarrier = GNUNET_TESTBED_barrier_init_ (slave->controller, |
781 | barrier->name, | 750 | barrier->name, |
782 | barrier->quorum, | 751 | barrier->quorum, |
783 | &wbarrier_status_cb, | 752 | &wbarrier_status_cb, |
784 | wrapper); | 753 | wrapper, |
754 | GNUNET_NO); | ||
785 | } | 755 | } |
786 | if (NULL == barrier->whead) /* No further propagation */ | 756 | if (NULL == barrier->whead) /* No further propagation */ |
787 | { | 757 | { |
@@ -856,4 +826,85 @@ GST_handle_barrier_cancel (void *cls, struct GNUNET_SERVER_Client *client, | |||
856 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 826 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
857 | } | 827 | } |
858 | 828 | ||
829 | |||
830 | /** | ||
831 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. | ||
832 | * This handler is queued in the main service and will handle the messages sent | ||
833 | * either from the testbed driver or from a high level controller | ||
834 | * | ||
835 | * @param cls NULL | ||
836 | * @param client identification of the client | ||
837 | * @param message the actual message | ||
838 | */ | ||
839 | void | ||
840 | GST_handle_barrier_status (void *cls, struct GNUNET_SERVER_Client *client, | ||
841 | const struct GNUNET_MessageHeader *message) | ||
842 | { | ||
843 | const struct GNUNET_TESTBED_BarrierStatusMsg *msg; | ||
844 | struct Barrier *barrier; | ||
845 | struct ClientCtx *client_ctx; | ||
846 | const char *name; | ||
847 | struct GNUNET_HashCode key; | ||
848 | enum GNUNET_TESTBED_BarrierStatus status; | ||
849 | uint16_t msize; | ||
850 | uint16_t name_len; | ||
851 | |||
852 | if (NULL == GST_context) | ||
853 | { | ||
854 | GNUNET_break_op (0); | ||
855 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
856 | return; | ||
857 | } | ||
858 | if (client != GST_context->client) | ||
859 | { | ||
860 | GNUNET_break_op (0); | ||
861 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
862 | return; | ||
863 | } | ||
864 | msize = ntohs (message->size); | ||
865 | if (msize <= sizeof (struct GNUNET_TESTBED_BarrierStatusMsg)) | ||
866 | { | ||
867 | GNUNET_break_op (0); | ||
868 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
869 | return; | ||
870 | } | ||
871 | msg = (const struct GNUNET_TESTBED_BarrierStatusMsg *) message; | ||
872 | status = ntohs (msg->status); | ||
873 | if (BARRIER_STATUS_CROSSED != status) | ||
874 | { | ||
875 | GNUNET_break_op (0); /* current we only expect BARRIER_CROSSED | ||
876 | status message this way */ | ||
877 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
878 | return; | ||
879 | } | ||
880 | name = msg->data; | ||
881 | name_len = ntohs (msg->name_len); | ||
882 | if ((sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len + 1) != msize) | ||
883 | { | ||
884 | GNUNET_break_op (0); | ||
885 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
886 | return; | ||
887 | } | ||
888 | if ('\0' != name[name_len]) | ||
889 | { | ||
890 | GNUNET_break_op (0); | ||
891 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
892 | return; | ||
893 | } | ||
894 | GNUNET_CRYPTO_hash (name, name_len, &key); | ||
895 | barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &key); | ||
896 | if (NULL == barrier) | ||
897 | { | ||
898 | GNUNET_break_op (0); | ||
899 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
900 | return; | ||
901 | } | ||
902 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
903 | while (NULL != (client_ctx = barrier->head)) /* Notify peers */ | ||
904 | { | ||
905 | queue_message (client_ctx, GNUNET_copy_message (message)); | ||
906 | GNUNET_CONTAINER_DLL_remove (barrier->head, barrier->tail, client_ctx); | ||
907 | } | ||
908 | } | ||
909 | |||
859 | /* end of gnunet-service-testbed_barriers.c */ | 910 | /* end of gnunet-service-testbed_barriers.c */ |
diff --git a/src/testbed/gnunet-service-testbed_barriers.h b/src/testbed/gnunet-service-testbed_barriers.h index ed1b339b0..a96812086 100644 --- a/src/testbed/gnunet-service-testbed_barriers.h +++ b/src/testbed/gnunet-service-testbed_barriers.h | |||
@@ -76,6 +76,20 @@ void | |||
76 | GST_handle_barrier_cancel (void *cls, struct GNUNET_SERVER_Client *client, | 76 | GST_handle_barrier_cancel (void *cls, struct GNUNET_SERVER_Client *client, |
77 | const struct GNUNET_MessageHeader *message); | 77 | const struct GNUNET_MessageHeader *message); |
78 | 78 | ||
79 | |||
80 | /** | ||
81 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. | ||
82 | * This handler is queued in the main service and will handle the messages sent | ||
83 | * either from the testbed driver or from a high level controller | ||
84 | * | ||
85 | * @param cls NULL | ||
86 | * @param client identification of the client | ||
87 | * @param message the actual message | ||
88 | */ | ||
89 | void | ||
90 | GST_handle_barrier_status (void *cls, struct GNUNET_SERVER_Client *client, | ||
91 | const struct GNUNET_MessageHeader *message); | ||
92 | |||
79 | #endif /* GNUNET_SERVER_TESTBED_BARRIERS_H_ */ | 93 | #endif /* GNUNET_SERVER_TESTBED_BARRIERS_H_ */ |
80 | 94 | ||
81 | /* end of gnunet-service-testbed_barriers.h */ | 95 | /* end of gnunet-service-testbed_barriers.h */ |
diff --git a/src/testbed/testbed_api_barriers.c b/src/testbed/testbed_api_barriers.c index 96fd3be66..3e4640309 100644 --- a/src/testbed/testbed_api_barriers.c +++ b/src/testbed/testbed_api_barriers.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "platform.h" | 27 | #include "platform.h" |
28 | #include "gnunet_testbed_service.h" | 28 | #include "gnunet_testbed_service.h" |
29 | #include "testbed_api.h" | 29 | #include "testbed_api.h" |
30 | #include "testbed_api_barriers.h" | ||
30 | 31 | ||
31 | /** | 32 | /** |
32 | * Logging shorthand | 33 | * Logging shorthand |
@@ -70,6 +71,10 @@ struct GNUNET_TESTBED_Barrier | |||
70 | */ | 71 | */ |
71 | void *cls; | 72 | void *cls; |
72 | 73 | ||
74 | /** | ||
75 | * Should the barrier crossed status message be echoed back to the controller? | ||
76 | */ | ||
77 | int echo; | ||
73 | }; | 78 | }; |
74 | 79 | ||
75 | 80 | ||
@@ -172,6 +177,8 @@ GNUNET_TESTBED_handle_barrier_status_ (struct GNUNET_TESTBED_Controller *c, | |||
172 | goto cleanup; | 177 | goto cleanup; |
173 | } | 178 | } |
174 | GNUNET_assert (NULL != barrier->cb); | 179 | GNUNET_assert (NULL != barrier->cb); |
180 | if ((GNUNET_YES == barrier->echo) && (BARRIER_STATUS_CROSSED == status)) | ||
181 | GNUNET_TESTBED_queue_message_ (c, GNUNET_copy_message (&msg->header)); | ||
175 | barrier->cb (barrier->cls, name, barrier, status, emsg); | 182 | barrier->cb (barrier->cls, name, barrier, status, emsg); |
176 | if (BARRIER_STATUS_INITIALISED == status) | 183 | if (BARRIER_STATUS_INITIALISED == status) |
177 | return GNUNET_OK; /* just initialised; skip cleanup */ | 184 | return GNUNET_OK; /* just initialised; skip cleanup */ |
@@ -196,13 +203,16 @@ GNUNET_TESTBED_handle_barrier_status_ (struct GNUNET_TESTBED_Controller *c, | |||
196 | * @param cb the callback to call when the barrier is reached or upon error. | 203 | * @param cb the callback to call when the barrier is reached or upon error. |
197 | * Cannot be NULL. | 204 | * Cannot be NULL. |
198 | * @param cls closure for the above callback | 205 | * @param cls closure for the above callback |
206 | * @param echo GNUNET_YES to echo the barrier crossed status message back to the | ||
207 | * controller | ||
199 | * @return barrier handle; NULL upon error | 208 | * @return barrier handle; NULL upon error |
200 | */ | 209 | */ |
201 | struct GNUNET_TESTBED_Barrier * | 210 | struct GNUNET_TESTBED_Barrier * |
202 | GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller, | 211 | GNUNET_TESTBED_barrier_init_ (struct GNUNET_TESTBED_Controller *controller, |
203 | const char *name, | 212 | const char *name, |
204 | unsigned int quorum, | 213 | unsigned int quorum, |
205 | GNUNET_TESTBED_barrier_status_cb cb, void *cls) | 214 | GNUNET_TESTBED_barrier_status_cb cb, void *cls, |
215 | int echo) | ||
206 | { | 216 | { |
207 | struct GNUNET_TESTBED_BarrierInit *msg; | 217 | struct GNUNET_TESTBED_BarrierInit *msg; |
208 | struct GNUNET_TESTBED_Barrier *barrier; | 218 | struct GNUNET_TESTBED_Barrier *barrier; |
@@ -229,6 +239,7 @@ GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller, | |||
229 | barrier->name = GNUNET_strdup (name); | 239 | barrier->name = GNUNET_strdup (name); |
230 | barrier->cb = cb; | 240 | barrier->cb = cb; |
231 | barrier->cls = cls; | 241 | barrier->cls = cls; |
242 | barrier->echo = echo; | ||
232 | (void) memcpy (&barrier->key, &key, sizeof (struct GNUNET_HashCode)); | 243 | (void) memcpy (&barrier->key, &key, sizeof (struct GNUNET_HashCode)); |
233 | GNUNET_assert (GNUNET_OK == | 244 | GNUNET_assert (GNUNET_OK == |
234 | GNUNET_CONTAINER_multihashmap_put (barrier_map, &barrier->key, | 245 | GNUNET_CONTAINER_multihashmap_put (barrier_map, &barrier->key, |
@@ -246,6 +257,30 @@ GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller, | |||
246 | 257 | ||
247 | 258 | ||
248 | /** | 259 | /** |
260 | * Initialise a barrier and call the given callback when the required percentage | ||
261 | * of peers (quorum) reach the barrier OR upon error. | ||
262 | * | ||
263 | * @param controller the handle to the controller | ||
264 | * @param name identification name of the barrier | ||
265 | * @param quorum the percentage of peers that is required to reach the barrier. | ||
266 | * Peers signal reaching a barrier by calling | ||
267 | * GNUNET_TESTBED_barrier_reached(). | ||
268 | * @param cb the callback to call when the barrier is reached or upon error. | ||
269 | * Cannot be NULL. | ||
270 | * @param cls closure for the above callback | ||
271 | * @return barrier handle; NULL upon error | ||
272 | */ | ||
273 | struct GNUNET_TESTBED_Barrier * | ||
274 | GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller, | ||
275 | const char *name, | ||
276 | unsigned int quorum, | ||
277 | GNUNET_TESTBED_barrier_status_cb cb, void *cls) | ||
278 | { | ||
279 | return GNUNET_TESTBED_barrier_init_ (controller, name, quorum, cb, cls, GNUNET_YES); | ||
280 | } | ||
281 | |||
282 | |||
283 | /** | ||
249 | * Cancel a barrier. | 284 | * Cancel a barrier. |
250 | * | 285 | * |
251 | * @param barrier the barrier handle | 286 | * @param barrier the barrier handle |
diff --git a/src/testbed/testbed_api_barriers.h b/src/testbed/testbed_api_barriers.h new file mode 100644 index 000000000..89aa56ca5 --- /dev/null +++ b/src/testbed/testbed_api_barriers.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2008--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 | /** | ||
22 | * @file testbed/testbed_api_barriers.h | ||
23 | * @brief interface for barriers API function that are used internally (not | ||
24 | * exposed as user API) | ||
25 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
26 | */ | ||
27 | |||
28 | #include "gnunet_testbed_service.h" | ||
29 | |||
30 | |||
31 | /** | ||
32 | * Initialise a barrier and call the given callback when the required percentage | ||
33 | * of peers (quorum) reach the barrier OR upon error. | ||
34 | * | ||
35 | * @param controller the handle to the controller | ||
36 | * @param name identification name of the barrier | ||
37 | * @param quorum the percentage of peers that is required to reach the barrier. | ||
38 | * Peers signal reaching a barrier by calling | ||
39 | * GNUNET_TESTBED_barrier_reached(). | ||
40 | * @param cb the callback to call when the barrier is reached or upon error. | ||
41 | * Cannot be NULL. | ||
42 | * @param cls closure for the above callback | ||
43 | * @param echo GNUNET_YES to echo the barrier crossed status message back to the | ||
44 | * controller | ||
45 | * @return barrier handle; NULL upon error | ||
46 | */ | ||
47 | struct GNUNET_TESTBED_Barrier * | ||
48 | GNUNET_TESTBED_barrier_init_ (struct GNUNET_TESTBED_Controller *controller, | ||
49 | const char *name, | ||
50 | unsigned int quorum, | ||
51 | GNUNET_TESTBED_barrier_status_cb cb, void *cls, | ||
52 | int echo); | ||