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/testbed/gnunet-service-testbed_barriers.c | |
parent | abe521f93a227ef120cd75c7d649782951e8eca5 (diff) | |
download | gnunet-9363d5db9dd612c1ec8be0f202da23aeaf09be49.tar.gz gnunet-9363d5db9dd612c1ec8be0f202da23aeaf09be49.zip |
- experiment driver propagates barrier crossed notification
Diffstat (limited to 'src/testbed/gnunet-service-testbed_barriers.c')
-rw-r--r-- | src/testbed/gnunet-service-testbed_barriers.c | 143 |
1 files changed, 97 insertions, 46 deletions
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 */ |