diff options
-rw-r--r-- | src/include/gnunet_testbed_service.h | 47 | ||||
-rw-r--r-- | src/testbed/gnunet-helper-testbed.c | 2 | ||||
-rw-r--r-- | src/testbed/gnunet-service-testbed_barriers.c | 19 | ||||
-rw-r--r-- | src/testbed/testbed.h | 7 | ||||
-rw-r--r-- | src/testbed/testbed_api_barriers.c | 215 |
5 files changed, 275 insertions, 15 deletions
diff --git a/src/include/gnunet_testbed_service.h b/src/include/gnunet_testbed_service.h index 1810c9f25..a99faf007 100644 --- a/src/include/gnunet_testbed_service.h +++ b/src/include/gnunet_testbed_service.h | |||
@@ -1551,6 +1551,53 @@ void | |||
1551 | GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier); | 1551 | GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier); |
1552 | 1552 | ||
1553 | 1553 | ||
1554 | /** | ||
1555 | * Opaque handle for barrier wait | ||
1556 | */ | ||
1557 | struct GNUNET_TESTBED_BarrierWaitHandle; | ||
1558 | |||
1559 | |||
1560 | /** | ||
1561 | * Functions of this type are to be given as acallback argumetn to | ||
1562 | * GNUNET_TESTBED_barrier_wait(). The callback will be called when the barrier | ||
1563 | * corresponding given in GNUNET_TESTBED_barrier_wait() is crossed or cancelled. | ||
1564 | * | ||
1565 | * @param cls closure pointer given to GNUNET_TESTBED_barrier_wait() | ||
1566 | * @param name the barrier name | ||
1567 | * @param status GNUNET_SYSERR in case of error while waiting for the barrier; | ||
1568 | * GNUNET_OK if the barrier is crossed | ||
1569 | */ | ||
1570 | typedef void (*GNUNET_TESTBED_barrier_wait_cb) (void *cls, | ||
1571 | const char *name, | ||
1572 | int estatus); | ||
1573 | |||
1574 | |||
1575 | /** | ||
1576 | * Wait for a barrier to be crossed. This function should be called by the | ||
1577 | * peers which have been started by the testbed. If the peer is not started by | ||
1578 | * testbed this function may return error | ||
1579 | * | ||
1580 | * @param name the name of the barrier | ||
1581 | * @param cb the barrier wait callback | ||
1582 | * @param cls the closure for the above callback | ||
1583 | * @return barrier wait handle which can be used to cancel the waiting at | ||
1584 | * anytime before the callback is called. NULL upon error. | ||
1585 | */ | ||
1586 | struct GNUNET_TESTBED_BarrierWaitHandle * | ||
1587 | GNUNET_TESTBED_barrier_wait (const char *name, | ||
1588 | GNUNET_TESTBED_barrier_wait_cb cb, | ||
1589 | void *cls); | ||
1590 | |||
1591 | |||
1592 | /** | ||
1593 | * Cancel a barrier wait handle | ||
1594 | * | ||
1595 | * @param h the barrier wait handle | ||
1596 | */ | ||
1597 | void | ||
1598 | GNUNET_TESTBED_barrier_wait_cancel (struct GNUNET_TESTBED_BarrierWaitHandle *h); | ||
1599 | |||
1600 | |||
1554 | #if 0 /* keep Emacsens' auto-indent happy */ | 1601 | #if 0 /* keep Emacsens' auto-indent happy */ |
1555 | { | 1602 | { |
1556 | #endif | 1603 | #endif |
diff --git a/src/testbed/gnunet-helper-testbed.c b/src/testbed/gnunet-helper-testbed.c index b2deb7293..88ef3f87d 100644 --- a/src/testbed/gnunet-helper-testbed.c +++ b/src/testbed/gnunet-helper-testbed.c | |||
@@ -421,6 +421,8 @@ tokenizer_cb (void *cls, void *client, | |||
421 | } | 421 | } |
422 | LOG_DEBUG ("Staring testbed with config: %s\n", config); | 422 | LOG_DEBUG ("Staring testbed with config: %s\n", config); |
423 | binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-testbed"); | 423 | binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-testbed"); |
424 | /* expose testbed configuration through env variable */ | ||
425 | GNUNET_assert (0 == setenv (ENV_TESTBED_CONFIG, config, 1)); | ||
424 | testbed = | 426 | testbed = |
425 | GNUNET_OS_start_process (PIPE_CONTROL, | 427 | GNUNET_OS_start_process (PIPE_CONTROL, |
426 | GNUNET_OS_INHERIT_STD_ERR /*verbose? */ , NULL, | 428 | GNUNET_OS_INHERIT_STD_ERR /*verbose? */ , NULL, |
diff --git a/src/testbed/gnunet-service-testbed_barriers.c b/src/testbed/gnunet-service-testbed_barriers.c index c16882032..71fd8ebce 100644 --- a/src/testbed/gnunet-service-testbed_barriers.c +++ b/src/testbed/gnunet-service-testbed_barriers.c | |||
@@ -224,10 +224,6 @@ struct Barrier | |||
224 | */ | 224 | */ |
225 | uint8_t quorum; | 225 | uint8_t quorum; |
226 | 226 | ||
227 | /** | ||
228 | * Was there a timeout while propagating initialisation | ||
229 | */ | ||
230 | uint8_t timedout; | ||
231 | }; | 227 | }; |
232 | 228 | ||
233 | 229 | ||
@@ -610,8 +606,9 @@ wbarrier_status_cb (void *cls, const char *name, | |||
610 | wrapper->hbarrier = NULL; | 606 | wrapper->hbarrier = NULL; |
611 | GNUNET_CONTAINER_DLL_remove (barrier->whead, barrier->wtail, wrapper); | 607 | GNUNET_CONTAINER_DLL_remove (barrier->whead, barrier->wtail, wrapper); |
612 | GNUNET_free (wrapper); | 608 | GNUNET_free (wrapper); |
613 | if (BARRIER_STATUS_ERROR == status) | 609 | switch (status) |
614 | { | 610 | { |
611 | case BARRIER_STATUS_ERROR: | ||
615 | LOG (GNUNET_ERROR_TYPE_ERROR, | 612 | LOG (GNUNET_ERROR_TYPE_ERROR, |
616 | "Initialising barrier `%s' failed at a sub-controller: %s\n", | 613 | "Initialising barrier `%s' failed at a sub-controller: %s\n", |
617 | barrier->name, (NULL != emsg) ? emsg : "NULL"); | 614 | barrier->name, (NULL != emsg) ? emsg : "NULL"); |
@@ -621,9 +618,6 @@ wbarrier_status_cb (void *cls, const char *name, | |||
621 | barrier->status = BARRIER_STATUS_ERROR; | 618 | barrier->status = BARRIER_STATUS_ERROR; |
622 | send_barrier_status_msg (barrier, emsg); | 619 | send_barrier_status_msg (barrier, emsg); |
623 | return; | 620 | return; |
624 | } | ||
625 | switch (status) | ||
626 | { | ||
627 | case BARRIER_STATUS_CROSSED: | 621 | case BARRIER_STATUS_CROSSED: |
628 | if (BARRIER_STATUS_INITIALISED != barrier->status) | 622 | if (BARRIER_STATUS_INITIALISED != barrier->status) |
629 | { | 623 | { |
@@ -637,7 +631,7 @@ wbarrier_status_cb (void *cls, const char *name, | |||
637 | barrier->status = BARRIER_STATUS_CROSSED; | 631 | barrier->status = BARRIER_STATUS_CROSSED; |
638 | send_barrier_status_msg (barrier, NULL); | 632 | send_barrier_status_msg (barrier, NULL); |
639 | } | 633 | } |
640 | break; | 634 | return; |
641 | case BARRIER_STATUS_INITIALISED: | 635 | case BARRIER_STATUS_INITIALISED: |
642 | if (0 != barrier->status) | 636 | if (0 != barrier->status) |
643 | { | 637 | { |
@@ -650,11 +644,8 @@ wbarrier_status_cb (void *cls, const char *name, | |||
650 | barrier->status = BARRIER_STATUS_INITIALISED; | 644 | barrier->status = BARRIER_STATUS_INITIALISED; |
651 | send_barrier_status_msg (barrier, NULL); | 645 | send_barrier_status_msg (barrier, NULL); |
652 | } | 646 | } |
653 | break; | 647 | return; |
654 | case BARRIER_STATUS_ERROR: | ||
655 | GNUNET_assert (0); | ||
656 | } | 648 | } |
657 | return; | ||
658 | } | 649 | } |
659 | 650 | ||
660 | 651 | ||
@@ -670,8 +661,6 @@ fwd_tout_barrier_init (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
670 | { | 661 | { |
671 | struct Barrier *barrier = cls; | 662 | struct Barrier *barrier = cls; |
672 | 663 | ||
673 | barrier->nslaves--; | ||
674 | barrier->timedout = GNUNET_YES; | ||
675 | cancel_wrappers (barrier); | 664 | cancel_wrappers (barrier); |
676 | barrier->status = BARRIER_STATUS_ERROR; | 665 | barrier->status = BARRIER_STATUS_ERROR; |
677 | send_barrier_status_msg (barrier, | 666 | send_barrier_status_msg (barrier, |
diff --git a/src/testbed/testbed.h b/src/testbed/testbed.h index 7b0406502..32dcd6ddd 100644 --- a/src/testbed/testbed.h +++ b/src/testbed/testbed.h | |||
@@ -774,6 +774,13 @@ struct GNUNET_TESTBED_ManagePeerServiceMessage | |||
774 | 774 | ||
775 | 775 | ||
776 | /** | 776 | /** |
777 | * The environmental variable which when available refers to the configuration | ||
778 | * file the local testbed controller is using | ||
779 | */ | ||
780 | #define ENV_TESTBED_CONFIG "GNUNET_TESTBED_CONTROLLER_CONFIG" | ||
781 | |||
782 | |||
783 | /** | ||
777 | * Message to initialise a barrier | 784 | * Message to initialise a barrier |
778 | */ | 785 | */ |
779 | struct GNUNET_TESTBED_BarrierInit | 786 | struct GNUNET_TESTBED_BarrierInit |
diff --git a/src/testbed/testbed_api_barriers.c b/src/testbed/testbed_api_barriers.c index 23d34ffe8..58f8ba00c 100644 --- a/src/testbed/testbed_api_barriers.c +++ b/src/testbed/testbed_api_barriers.c | |||
@@ -241,4 +241,219 @@ GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier) | |||
241 | barrier_remove (barrier); | 241 | barrier_remove (barrier); |
242 | } | 242 | } |
243 | 243 | ||
244 | |||
245 | /** | ||
246 | * Barrier wait handle | ||
247 | */ | ||
248 | struct GNUNET_TESTBED_BarrierWaitHandle | ||
249 | { | ||
250 | /** | ||
251 | * The name of the barrier | ||
252 | */ | ||
253 | char *name; | ||
254 | |||
255 | /** | ||
256 | * Then configuration used for the client connection | ||
257 | */ | ||
258 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
259 | |||
260 | /** | ||
261 | * The client connection | ||
262 | */ | ||
263 | struct GNUNET_CLIENT_Connection *conn; | ||
264 | |||
265 | /** | ||
266 | * Transmit handle | ||
267 | */ | ||
268 | struct GNUNET_CLIENT_TransmitHandle *tx; | ||
269 | |||
270 | /** | ||
271 | * The message to transmit with tx | ||
272 | */ | ||
273 | struct GNUNET_MessageHeader *msg; | ||
274 | |||
275 | /** | ||
276 | * The barrier wait callback | ||
277 | */ | ||
278 | GNUNET_TESTBED_barrier_wait_cb cb; | ||
279 | |||
280 | /** | ||
281 | * The closure for the above callback | ||
282 | */ | ||
283 | void *cls; | ||
284 | }; | ||
285 | |||
286 | |||
287 | /** | ||
288 | * Function to destroy barrier wait handle | ||
289 | * | ||
290 | * @param h the handle to destroy | ||
291 | */ | ||
292 | static void | ||
293 | destroy_handle (struct GNUNET_TESTBED_BarrierWaitHandle *h) | ||
294 | { | ||
295 | GNUNET_free (h->name); | ||
296 | if (NULL != h->tx) | ||
297 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->tx); | ||
298 | if (NULL != h->conn) | ||
299 | GNUNET_CLIENT_disconnect (h->conn); | ||
300 | if (NULL != h->msg) | ||
301 | GNUNET_free (h->msg); | ||
302 | GNUNET_CONFIGURATION_destroy (h->cfg); | ||
303 | GNUNET_free (h); | ||
304 | } | ||
305 | |||
306 | |||
307 | /** | ||
308 | * Type of a function to call when we receive a message | ||
309 | * from the service. | ||
310 | * | ||
311 | * @param cls closure | ||
312 | * @param msg message received, NULL on timeout or fatal error | ||
313 | */ | ||
314 | static void | ||
315 | receive_handler (void *cls, const struct GNUNET_MessageHeader *message) | ||
316 | { | ||
317 | struct GNUNET_TESTBED_BarrierWaitHandle *h = cls; | ||
318 | const struct GNUNET_TESTBED_BarrierStatusMsg *msg; | ||
319 | uint16_t msize; | ||
320 | |||
321 | if (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS != ntohs (message->type)) | ||
322 | { | ||
323 | GNUNET_break_op (0); | ||
324 | goto fail; | ||
325 | } | ||
326 | msize = ntohs (message->size); | ||
327 | if (msize <= sizeof (struct GNUNET_TESTBED_BarrierStatusMsg)) | ||
328 | { | ||
329 | GNUNET_break_op (0); | ||
330 | goto fail; | ||
331 | } | ||
332 | msg = (const struct GNUNET_TESTBED_BarrierStatusMsg *) message; | ||
333 | switch (ntohs (msg->status)) | ||
334 | { | ||
335 | case BARRIER_STATUS_ERROR: | ||
336 | goto fail; | ||
337 | case BARRIER_STATUS_INITIALISED: | ||
338 | GNUNET_break (0); /* FIXME */ | ||
339 | goto destroy; | ||
340 | case BARRIER_STATUS_CROSSED: | ||
341 | h->cb (h->cls, h->name, GNUNET_OK); | ||
342 | goto destroy; | ||
343 | } | ||
344 | |||
345 | fail: | ||
346 | h->cb (h->cls, h->name, GNUNET_SYSERR); | ||
347 | |||
348 | destroy: | ||
349 | destroy_handle (h); | ||
350 | } | ||
351 | |||
352 | |||
353 | /** | ||
354 | * Function called to notify a client about the connection | ||
355 | * begin ready to queue more data. "buf" will be | ||
356 | * NULL and "size" zero if the connection was closed for | ||
357 | * writing in the meantime. | ||
358 | * | ||
359 | * @param cls closure | ||
360 | * @param size number of bytes available in buf | ||
361 | * @param buf where the callee should write the message | ||
362 | * @return number of bytes written to buf | ||
363 | */ | ||
364 | static size_t | ||
365 | transmit_notify (void *cls, size_t size, void *buf) | ||
366 | { | ||
367 | struct GNUNET_TESTBED_BarrierWaitHandle *h = cls; | ||
368 | uint16_t msize; | ||
369 | |||
370 | h->tx = NULL; | ||
371 | if ((0 == size) || (NULL == buf)) | ||
372 | { | ||
373 | destroy_handle (h); | ||
374 | return 0; | ||
375 | } | ||
376 | msize = htons (h->msg->size); | ||
377 | GNUNET_assert (msize <= size); | ||
378 | (void) memcpy (buf, h->msg, msize); | ||
379 | GNUNET_free (h->msg); | ||
380 | h->msg = NULL; | ||
381 | GNUNET_CLIENT_receive (h->conn, &receive_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); | ||
382 | return msize; | ||
383 | } | ||
384 | |||
385 | |||
386 | /** | ||
387 | * Wait for a barrier to be crossed. This function should be called by the | ||
388 | * peers which have been started by the testbed. If the peer is not started by | ||
389 | * testbed this function may return error | ||
390 | * | ||
391 | * @param name the name of the barrier | ||
392 | * @param cb the barrier wait callback | ||
393 | * @param cls the closure for the above callback | ||
394 | * @return barrier wait handle which can be used to cancel the waiting at | ||
395 | * anytime before the callback is called. NULL upon error. | ||
396 | */ | ||
397 | struct GNUNET_TESTBED_BarrierWaitHandle * | ||
398 | GNUNET_TESTBED_barrier_wait (const char *name, | ||
399 | GNUNET_TESTBED_barrier_wait_cb cb, | ||
400 | void *cls) | ||
401 | { | ||
402 | struct GNUNET_TESTBED_BarrierWait *msg; | ||
403 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
404 | struct GNUNET_TESTBED_BarrierWaitHandle *h; | ||
405 | char *cfg_filename; | ||
406 | size_t name_len; | ||
407 | uint16_t msize; | ||
408 | |||
409 | GNUNET_assert (NULL != cb); | ||
410 | GNUNET_assert (NULL != name); | ||
411 | cfg_filename = getenv (ENV_TESTBED_CONFIG); | ||
412 | if (NULL == cfg_filename) | ||
413 | return NULL; | ||
414 | cfg = GNUNET_CONFIGURATION_create (); | ||
415 | if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfg_filename)); | ||
416 | { | ||
417 | GNUNET_CONFIGURATION_destroy (cfg); | ||
418 | return NULL; | ||
419 | } | ||
420 | h = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_BarrierWaitHandle)); | ||
421 | h->name = GNUNET_strdup (name); | ||
422 | h->cfg = cfg; | ||
423 | h->conn = GNUNET_CLIENT_connect ("testbed-barrier", h->cfg); | ||
424 | h->cb = cb; | ||
425 | h->cls = cls; | ||
426 | if (NULL == h->conn) | ||
427 | { | ||
428 | destroy_handle (h); | ||
429 | return NULL; | ||
430 | } | ||
431 | name_len = strlen (name); | ||
432 | msize = sizeof (struct GNUNET_TESTBED_BarrierWait) + name_len; | ||
433 | msg = GNUNET_malloc (msize); | ||
434 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT); | ||
435 | msg->header.size = htons (msize); | ||
436 | (void) memcpy (msg->name, name, name_len); | ||
437 | h->msg = &msg->header; | ||
438 | h->tx = | ||
439 | GNUNET_CLIENT_notify_transmit_ready (h->conn, msize, | ||
440 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
441 | GNUNET_NO, | ||
442 | &transmit_notify, | ||
443 | h); | ||
444 | return h; | ||
445 | } | ||
446 | |||
447 | |||
448 | /** | ||
449 | * Cancel a barrier wait handle | ||
450 | * | ||
451 | * @param h the barrier wait handle | ||
452 | */ | ||
453 | void | ||
454 | GNUNET_TESTBED_barrier_wait_cancel (struct GNUNET_TESTBED_BarrierWaitHandle *h) | ||
455 | { | ||
456 | destroy_handle (h); | ||
457 | } | ||
458 | |||
244 | /* end of testbed_api_barriers.c */ | 459 | /* end of testbed_api_barriers.c */ |