aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-09-10 12:18:07 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-09-10 12:18:07 +0000
commit9363d5db9dd612c1ec8be0f202da23aeaf09be49 (patch)
treec10ade1161826fdadd24f1e1a2e350596f4a0a19 /src
parentabe521f93a227ef120cd75c7d649782951e8eca5 (diff)
downloadgnunet-9363d5db9dd612c1ec8be0f202da23aeaf09be49.tar.gz
gnunet-9363d5db9dd612c1ec8be0f202da23aeaf09be49.zip
- experiment driver propagates barrier crossed notification
Diffstat (limited to 'src')
-rw-r--r--src/testbed/gnunet-service-testbed.c2
-rw-r--r--src/testbed/gnunet-service-testbed_barriers.c143
-rw-r--r--src/testbed/gnunet-service-testbed_barriers.h14
-rw-r--r--src/testbed/testbed_api_barriers.c43
-rw-r--r--src/testbed/testbed_api_barriers.h52
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 */
446static void
447notify_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 */
839void
840GST_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
76GST_handle_barrier_cancel (void *cls, struct GNUNET_SERVER_Client *client, 76GST_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 */
89void
90GST_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 */
201struct GNUNET_TESTBED_Barrier * 210struct GNUNET_TESTBED_Barrier *
202GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller, 211GNUNET_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 */
273struct GNUNET_TESTBED_Barrier *
274GNUNET_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 */
47struct GNUNET_TESTBED_Barrier *
48GNUNET_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);