diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-09-02 10:01:01 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-09-02 10:01:01 +0000 |
commit | 719fb81dbaf034f624abaf6cc0a51c05446191f4 (patch) | |
tree | f31237c562e3e442ad20cd9c0308bcd13db7ae2f /src/testbed | |
parent | 6c684b3367b9f21ea46b0565b6e4aac8daf85f51 (diff) | |
download | gnunet-719fb81dbaf034f624abaf6cc0a51c05446191f4.tar.gz gnunet-719fb81dbaf034f624abaf6cc0a51c05446191f4.zip |
- more barrier stuff
Diffstat (limited to 'src/testbed')
-rw-r--r-- | src/testbed/gnunet-service-testbed_barriers.c | 160 | ||||
-rw-r--r-- | src/testbed/testbed.h | 9 | ||||
-rw-r--r-- | src/testbed/testbed_api.c | 2 | ||||
-rw-r--r-- | src/testbed/testbed_api.h | 2 | ||||
-rw-r--r-- | src/testbed/testbed_api_barriers.c | 12 |
5 files changed, 141 insertions, 44 deletions
diff --git a/src/testbed/gnunet-service-testbed_barriers.c b/src/testbed/gnunet-service-testbed_barriers.c index c12075d66..e0d0e2f18 100644 --- a/src/testbed/gnunet-service-testbed_barriers.c +++ b/src/testbed/gnunet-service-testbed_barriers.c | |||
@@ -153,6 +153,11 @@ struct Barrier | |||
153 | struct GNUNET_HashCode hash; | 153 | struct GNUNET_HashCode hash; |
154 | 154 | ||
155 | /** | 155 | /** |
156 | * The client handle to the master controller | ||
157 | */ | ||
158 | struct GNUNET_SERVER_Client *client; | ||
159 | |||
160 | /** | ||
156 | * The name of the barrier | 161 | * The name of the barrier |
157 | */ | 162 | */ |
158 | char *name; | 163 | char *name; |
@@ -178,6 +183,16 @@ struct Barrier | |||
178 | struct WBarrier *wtail; | 183 | struct WBarrier *wtail; |
179 | 184 | ||
180 | /** | 185 | /** |
186 | * Identifier for the timeout task | ||
187 | */ | ||
188 | GNUNET_SCHEDULER_TaskIdentifier tout_task; | ||
189 | |||
190 | /** | ||
191 | * The status of this barrier | ||
192 | */ | ||
193 | enum GNUNET_TESTBED_BarrierStatus status; | ||
194 | |||
195 | /** | ||
181 | * Number of barriers wrapped in the above DLL | 196 | * Number of barriers wrapped in the above DLL |
182 | */ | 197 | */ |
183 | unsigned int num_wbarriers; | 198 | unsigned int num_wbarriers; |
@@ -188,6 +203,11 @@ struct Barrier | |||
188 | unsigned int num_wbarriers_reached; | 203 | unsigned int num_wbarriers_reached; |
189 | 204 | ||
190 | /** | 205 | /** |
206 | * Number of wrapped barrier initialised so far | ||
207 | */ | ||
208 | unsigned int num_wbarriers_inited; | ||
209 | |||
210 | /** | ||
191 | * Number of peers which have reached this barrier | 211 | * Number of peers which have reached this barrier |
192 | */ | 212 | */ |
193 | unsigned int nreached; | 213 | unsigned int nreached; |
@@ -287,7 +307,6 @@ queue_message (struct ClientCtx *ctx, struct GNUNET_MessageHeader *msg) | |||
287 | } | 307 | } |
288 | 308 | ||
289 | 309 | ||
290 | #if 0 | ||
291 | /** | 310 | /** |
292 | * Function to remove a barrier from the barrier map and cleanup resources | 311 | * Function to remove a barrier from the barrier map and cleanup resources |
293 | * occupied by a barrier | 312 | * occupied by a barrier |
@@ -301,33 +320,63 @@ remove_barrier (struct Barrier *barrier) | |||
301 | &barrier->hash, | 320 | &barrier->hash, |
302 | barrier)); | 321 | barrier)); |
303 | GNUNET_free (barrier->name); | 322 | GNUNET_free (barrier->name); |
323 | if (NULL != barrier->client) | ||
324 | GNUNET_SERVER_client_drop (barrier->client); | ||
304 | GNUNET_free (barrier); | 325 | GNUNET_free (barrier); |
305 | } | 326 | } |
306 | 327 | ||
307 | 328 | ||
308 | /** | 329 | /** |
309 | * Function called upon timeout while waiting for a response from the | 330 | * Cancels all subcontroller barrier handles |
310 | * subcontrollers to barrier init message | ||
311 | * | 331 | * |
312 | * @param | 332 | * @param barrier the local barrier |
313 | * @return | ||
314 | */ | 333 | */ |
315 | static void | 334 | static void |
316 | fwd_tout_barrier_init (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 335 | cancel_wrappers (struct Barrier *barrier) |
317 | { | 336 | { |
318 | struct ForwardedOperationContext *foctx = cls; | 337 | struct WBarrier *wrapper; |
319 | struct Barrier *barrier = foctx->cls; | 338 | |
320 | 339 | while (NULL != (wrapper = barrier->whead)) | |
321 | barrier->nslaves--; | ||
322 | barrier->timedout = GNUNET_YES; | ||
323 | if (0 == barrier->nslaves) | ||
324 | { | 340 | { |
325 | GST_send_operation_fail_msg (foctx->client, foctx->operation_id, | 341 | GNUNET_TESTBED_barrier_cancel (wrapper->hbarrier); |
326 | "Timeout while contacting a slave controller"); | 342 | GNUNET_CONTAINER_DLL_remove (barrier->whead, barrier->wtail, wrapper); |
327 | remove_barrier (barrier); | 343 | GNUNET_free (wrapper); |
328 | } | 344 | } |
329 | } | 345 | } |
330 | #endif | 346 | |
347 | |||
348 | /** | ||
349 | * Sends a barrier failed message | ||
350 | * | ||
351 | * @param barrier the corresponding barrier | ||
352 | * @param status the status of the barrier | ||
353 | * @param emsg the error message; should be non-NULL for | ||
354 | * status=BARRIER_STATUS_ERROR | ||
355 | */ | ||
356 | static void | ||
357 | send_barrier_status_msg (struct Barrier *barrier, | ||
358 | enum GNUNET_TESTBED_BarrierStatus status, | ||
359 | const char *emsg) | ||
360 | { | ||
361 | struct GNUNET_TESTBED_BarrierStatusMsg *msg; | ||
362 | size_t name_len; | ||
363 | uint16_t msize; | ||
364 | |||
365 | GNUNET_assert ((NULL == emsg) || (BARRIER_STATUS_ERROR == status)); | ||
366 | name_len = strlen (barrier->name) + 1; | ||
367 | msize = sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) | ||
368 | + name_len | ||
369 | + (NULL == emsg) ? 0 : strlen (emsg) + 1; | ||
370 | msg = GNUNET_malloc (msize); | ||
371 | msg->status = htons (status); | ||
372 | msg->name_len = htons (name_len); | ||
373 | (void) memcpy (msg->data, barrier->name, name_len); | ||
374 | if (NULL != emsg) | ||
375 | (void) memcpy (msg->data + name_len, emsg, strlen (emsg) + 1); | ||
376 | GST_queue_message (barrier->client, &msg->header); | ||
377 | } | ||
378 | |||
379 | |||
331 | 380 | ||
332 | /** | 381 | /** |
333 | * Task for sending barrier crossed notifications to waiting client | 382 | * Task for sending barrier crossed notifications to waiting client |
@@ -340,13 +389,13 @@ notify_task_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
340 | { | 389 | { |
341 | struct Barrier *barrier = cls; | 390 | struct Barrier *barrier = cls; |
342 | struct ClientCtx *client_ctx; | 391 | struct ClientCtx *client_ctx; |
343 | struct GNUNET_TESTBED_BarrierStatus *msg; | 392 | struct GNUNET_TESTBED_BarrierStatusMsg *msg; |
344 | struct GNUNET_MessageHeader *dup_msg; | 393 | struct GNUNET_MessageHeader *dup_msg; |
345 | uint16_t name_len; | 394 | uint16_t name_len; |
346 | uint16_t msize; | 395 | uint16_t msize; |
347 | 396 | ||
348 | name_len = strlen (barrier->name) + 1; | 397 | name_len = strlen (barrier->name) + 1; |
349 | msize = sizeof (struct GNUNET_TESTBED_BarrierStatus) + name_len; | 398 | msize = sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len; |
350 | msg = GNUNET_malloc (msize); | 399 | msg = GNUNET_malloc (msize); |
351 | msg->header.size = htons (msize); | 400 | msg->header.size = htons (msize); |
352 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS); | 401 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS); |
@@ -505,8 +554,9 @@ GST_barriers_stop () | |||
505 | */ | 554 | */ |
506 | static void | 555 | static void |
507 | wbarrier_status_cb (void *cls, const char *name, | 556 | wbarrier_status_cb (void *cls, const char *name, |
508 | struct GNUNET_TESTBED_Barrier *b_, | 557 | struct GNUNET_TESTBED_Barrier *b_, |
509 | int status, const char *emsg) | 558 | enum GNUNET_TESTBED_BarrierStatus status, |
559 | const char *emsg) | ||
510 | { | 560 | { |
511 | struct WBarrier *wrapper = cls; | 561 | struct WBarrier *wrapper = cls; |
512 | struct Barrier *barrier = wrapper->barrier; | 562 | struct Barrier *barrier = wrapper->barrier; |
@@ -515,32 +565,59 @@ wbarrier_status_cb (void *cls, const char *name, | |||
515 | wrapper->hbarrier = NULL; | 565 | wrapper->hbarrier = NULL; |
516 | GNUNET_CONTAINER_DLL_remove (barrier->whead, barrier->wtail, wrapper); | 566 | GNUNET_CONTAINER_DLL_remove (barrier->whead, barrier->wtail, wrapper); |
517 | GNUNET_free (wrapper); | 567 | GNUNET_free (wrapper); |
518 | if (GNUNET_SYSERR == status) | 568 | if (BARRIER_STATUS_ERROR == status) |
519 | { | 569 | { |
520 | LOG (GNUNET_ERROR_TYPE_ERROR, | 570 | LOG (GNUNET_ERROR_TYPE_ERROR, |
521 | "Initialising barrier (%s) failed at a sub-controller: %s\n", | 571 | "Initialising barrier `%s' failed at a sub-controller: %s\n", |
522 | barrier->name, (NULL != emsg) ? emsg : "NULL"); | 572 | barrier->name, (NULL != emsg) ? emsg : "NULL"); |
523 | while (NULL != (wrapper = barrier->whead)) | 573 | cancel_wrappers (barrier); |
524 | { | 574 | if (NULL == emsg) |
525 | GNUNET_TESTBED_barrier_cancel (wrapper->hbarrier); | 575 | emsg = "Initialisation failed at a sub-controller"; |
526 | GNUNET_CONTAINER_DLL_remove (barrier->whead, barrier->wtail, wrapper); | 576 | send_barrier_status_msg (barrier, BARRIER_STATUS_ERROR, emsg); |
527 | GNUNET_free (wrapper); | 577 | return; |
528 | } | ||
529 | /* Send parent controller failure message */ | ||
530 | GNUNET_break (0); | ||
531 | } | 578 | } |
532 | barrier->num_wbarriers_reached++; | 579 | switch (status) |
533 | if ((barrier->num_wbarriers_reached == barrier->num_wbarriers) | ||
534 | && (LOCAL_QUORUM_REACHED (barrier))) | ||
535 | { | 580 | { |
536 | /* Send parent controller success status message */ | 581 | case BARRIER_STATUS_CROSSED: |
537 | GNUNET_break (0); | 582 | barrier->num_wbarriers_reached++; |
583 | if ((barrier->num_wbarriers_reached == barrier->num_wbarriers) | ||
584 | && (LOCAL_QUORUM_REACHED (barrier))) | ||
585 | send_barrier_status_msg (barrier, BARRIER_STATUS_CROSSED, NULL); | ||
586 | break; | ||
587 | case BARRIER_STATUS_INITIALISED: | ||
588 | barrier->num_wbarriers_inited++; | ||
589 | if (barrier->num_wbarriers_inited == barrier->num_wbarriers) | ||
590 | send_barrier_status_msg (barrier, BARRIER_STATUS_INITIALISED, NULL); | ||
591 | break; | ||
592 | case BARRIER_STATUS_ERROR: | ||
593 | GNUNET_assert (0); | ||
538 | } | 594 | } |
539 | return; | 595 | return; |
540 | } | 596 | } |
541 | 597 | ||
542 | 598 | ||
543 | /** | 599 | /** |
600 | * Function called upon timeout while waiting for a response from the | ||
601 | * subcontrollers to barrier init message | ||
602 | * | ||
603 | * @param | ||
604 | * @return | ||
605 | */ | ||
606 | static void | ||
607 | fwd_tout_barrier_init (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
608 | { | ||
609 | struct Barrier *barrier = cls; | ||
610 | |||
611 | barrier->nslaves--; | ||
612 | barrier->timedout = GNUNET_YES; | ||
613 | cancel_wrappers (barrier); | ||
614 | send_barrier_status_msg (barrier, BARRIER_STATUS_ERROR, | ||
615 | "Timedout while propagating barrier initialisation\n"); | ||
616 | remove_barrier (barrier); | ||
617 | } | ||
618 | |||
619 | |||
620 | /** | ||
544 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This | 621 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This |
545 | * message should always come from a parent controller or the testbed API if we | 622 | * message should always come from a parent controller or the testbed API if we |
546 | * are the root controller. | 623 | * are the root controller. |
@@ -603,6 +680,8 @@ GST_handle_barrier_init (void *cls, struct GNUNET_SERVER_Client *client, | |||
603 | barrier->name = GNUNET_malloc (name_len + 1); | 680 | barrier->name = GNUNET_malloc (name_len + 1); |
604 | barrier->name[name_len] = '\0'; | 681 | barrier->name[name_len] = '\0'; |
605 | (void) memcpy (barrier->name, name, name_len); | 682 | (void) memcpy (barrier->name, name, name_len); |
683 | barrier->client = client; | ||
684 | GNUNET_SERVER_client_keep (client); | ||
606 | GNUNET_assert (GNUNET_OK == | 685 | GNUNET_assert (GNUNET_OK == |
607 | GNUNET_CONTAINER_multihashmap_put (barrier_map, | 686 | GNUNET_CONTAINER_multihashmap_put (barrier_map, |
608 | &barrier->hash, | 687 | &barrier->hash, |
@@ -621,10 +700,19 @@ GST_handle_barrier_init (void *cls, struct GNUNET_SERVER_Client *client, | |||
621 | } | 700 | } |
622 | wrapper = GNUNET_malloc (sizeof (struct WBarrier)); | 701 | wrapper = GNUNET_malloc (sizeof (struct WBarrier)); |
623 | wrapper->barrier = barrier; | 702 | wrapper->barrier = barrier; |
703 | GNUNET_CONTAINER_DLL_insert_tail (barrier->whead, barrier->wtail, wrapper); | ||
624 | wrapper->hbarrier = GNUNET_TESTBED_barrier_init (slave->controller, | 704 | wrapper->hbarrier = GNUNET_TESTBED_barrier_init (slave->controller, |
625 | barrier->name, | 705 | barrier->name, |
626 | barrier->quorum, | 706 | barrier->quorum, |
627 | &wbarrier_status_cb, | 707 | &wbarrier_status_cb, |
628 | wrapper); | 708 | wrapper); |
629 | } | 709 | } |
710 | if (NULL == barrier->whead) /* No further propagation */ | ||
711 | send_barrier_status_msg (barrier, BARRIER_STATUS_INITIALISED, NULL); | ||
712 | else | ||
713 | barrier->tout_task = GNUNET_SCHEDULER_add_delayed (MESSAGE_SEND_TIMEOUT (30), | ||
714 | &fwd_tout_barrier_init, | ||
715 | barrier); | ||
630 | } | 716 | } |
717 | |||
718 | /* end of gnunet-service-testbed_barriers.c */ | ||
diff --git a/src/testbed/testbed.h b/src/testbed/testbed.h index 3b159591d..73cf8c294 100644 --- a/src/testbed/testbed.h +++ b/src/testbed/testbed.h | |||
@@ -768,6 +768,11 @@ struct GNUNET_TESTBED_ManagePeerServiceMessage | |||
768 | }; | 768 | }; |
769 | 769 | ||
770 | 770 | ||
771 | /**************************************/ | ||
772 | /* Barriers IPC messages and protocol */ | ||
773 | /**************************************/ | ||
774 | |||
775 | |||
771 | /** | 776 | /** |
772 | * Message to initialise a barrier | 777 | * Message to initialise a barrier |
773 | */ | 778 | */ |
@@ -803,7 +808,7 @@ struct GNUNET_TESTBED_BarrierInit | |||
803 | /** | 808 | /** |
804 | * Message for signalling status changes of a barrier | 809 | * Message for signalling status changes of a barrier |
805 | */ | 810 | */ |
806 | struct GNUNET_TESTBED_BarrierStatus | 811 | struct GNUNET_TESTBED_BarrierStatusMsg |
807 | { | 812 | { |
808 | /** | 813 | /** |
809 | * Type is GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS | 814 | * Type is GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS |
@@ -811,7 +816,7 @@ struct GNUNET_TESTBED_BarrierStatus | |||
811 | struct GNUNET_MessageHeader header; | 816 | struct GNUNET_MessageHeader header; |
812 | 817 | ||
813 | /** | 818 | /** |
814 | * status. 0 to signal success (barrier is crossed). 1 for error. | 819 | * status. Use enumerated values of enum BarrierStatus |
815 | */ | 820 | */ |
816 | uint16_t status; | 821 | uint16_t status; |
817 | 822 | ||
diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c index 0a109aa7f..d5486b1c3 100644 --- a/src/testbed/testbed_api.c +++ b/src/testbed/testbed_api.c | |||
@@ -1163,7 +1163,7 @@ message_handler (void *cls, const struct GNUNET_MessageHeader *msg) | |||
1163 | status = | 1163 | status = |
1164 | GNUNET_TESTBED_handle_barrier_status_ (c, | 1164 | GNUNET_TESTBED_handle_barrier_status_ (c, |
1165 | (const struct | 1165 | (const struct |
1166 | GNUNET_TESTBED_BarrierStatus *) | 1166 | GNUNET_TESTBED_BarrierStatusMsg *) |
1167 | msg); | 1167 | msg); |
1168 | break; | 1168 | break; |
1169 | default: | 1169 | default: |
diff --git a/src/testbed/testbed_api.h b/src/testbed/testbed_api.h index f658c08dd..39a2f711a 100644 --- a/src/testbed/testbed_api.h +++ b/src/testbed/testbed_api.h | |||
@@ -508,7 +508,7 @@ GNUNET_TESTBED_controller_link_ (void *op_cls, | |||
508 | */ | 508 | */ |
509 | int | 509 | int |
510 | GNUNET_TESTBED_handle_barrier_status_ (struct GNUNET_TESTBED_Controller *c, | 510 | GNUNET_TESTBED_handle_barrier_status_ (struct GNUNET_TESTBED_Controller *c, |
511 | const struct GNUNET_TESTBED_BarrierStatus | 511 | const struct GNUNET_TESTBED_BarrierStatusMsg |
512 | *msg); | 512 | *msg); |
513 | 513 | ||
514 | 514 | ||
diff --git a/src/testbed/testbed_api_barriers.c b/src/testbed/testbed_api_barriers.c index 231e00600..ab468a088 100644 --- a/src/testbed/testbed_api_barriers.c +++ b/src/testbed/testbed_api_barriers.c | |||
@@ -102,7 +102,7 @@ barrier_remove (struct GNUNET_TESTBED_Barrier *barrier) | |||
102 | */ | 102 | */ |
103 | int | 103 | int |
104 | GNUNET_TESTBED_handle_barrier_status_ (struct GNUNET_TESTBED_Controller *c, | 104 | GNUNET_TESTBED_handle_barrier_status_ (struct GNUNET_TESTBED_Controller *c, |
105 | const struct GNUNET_TESTBED_BarrierStatus | 105 | const struct GNUNET_TESTBED_BarrierStatusMsg |
106 | *msg) | 106 | *msg) |
107 | { | 107 | { |
108 | struct GNUNET_TESTBED_Barrier *barrier; | 108 | struct GNUNET_TESTBED_Barrier *barrier; |
@@ -119,17 +119,17 @@ GNUNET_TESTBED_handle_barrier_status_ (struct GNUNET_TESTBED_Controller *c, | |||
119 | msize = ntohs (msg->header.size); | 119 | msize = ntohs (msg->header.size); |
120 | name = msg->data; | 120 | name = msg->data; |
121 | name_len = ntohs (msg->name_len); | 121 | name_len = ntohs (msg->name_len); |
122 | if ( (sizeof (struct GNUNET_TESTBED_BarrierStatus) + name_len + 1 > msize) | 122 | if ( (sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len + 1 > msize) |
123 | || ('\0' != name[name_len]) ) | 123 | || ('\0' != name[name_len]) ) |
124 | { | 124 | { |
125 | GNUNET_break_op (0); | 125 | GNUNET_break_op (0); |
126 | return GNUNET_SYSERR; | 126 | return GNUNET_SYSERR; |
127 | } | 127 | } |
128 | status = ntohs (msg->status); | 128 | status = ntohs (msg->status); |
129 | if (0 != status) | 129 | if (BARRIER_STATUS_ERROR == status) |
130 | { | 130 | { |
131 | status = -1; | 131 | status = -1; |
132 | emsg_len = msize - (sizeof (struct GNUNET_TESTBED_BarrierStatus) + name_len | 132 | emsg_len = msize - (sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len |
133 | + 1); | 133 | + 1); |
134 | if (0 == emsg_len) | 134 | if (0 == emsg_len) |
135 | { | 135 | { |
@@ -150,6 +150,8 @@ GNUNET_TESTBED_handle_barrier_status_ (struct GNUNET_TESTBED_Controller *c, | |||
150 | goto cleanup; | 150 | goto cleanup; |
151 | GNUNET_assert (NULL != barrier->cb); | 151 | GNUNET_assert (NULL != barrier->cb); |
152 | barrier->cb (barrier->cls, name, barrier, status, emsg); | 152 | barrier->cb (barrier->cls, name, barrier, status, emsg); |
153 | if (BARRIER_STATUS_INITIALISED == status) | ||
154 | return GNUNET_OK; /* just initialised; skip cleanup */ | ||
153 | 155 | ||
154 | cleanup: | 156 | cleanup: |
155 | GNUNET_free_non_null (emsg); | 157 | GNUNET_free_non_null (emsg); |
@@ -219,3 +221,5 @@ GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier) | |||
219 | { | 221 | { |
220 | barrier_remove (barrier); | 222 | barrier_remove (barrier); |
221 | } | 223 | } |
224 | |||
225 | /* end of testbed_api_barriers.c */ | ||