aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_testbed_service.h47
-rw-r--r--src/testbed/gnunet-helper-testbed.c2
-rw-r--r--src/testbed/gnunet-service-testbed_barriers.c19
-rw-r--r--src/testbed/testbed.h7
-rw-r--r--src/testbed/testbed_api_barriers.c215
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
1551GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier); 1551GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier);
1552 1552
1553 1553
1554/**
1555 * Opaque handle for barrier wait
1556 */
1557struct 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 */
1570typedef 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 */
1586struct GNUNET_TESTBED_BarrierWaitHandle *
1587GNUNET_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 */
1597void
1598GNUNET_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 */
779struct GNUNET_TESTBED_BarrierInit 786struct 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 */
248struct 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 */
292static void
293destroy_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 */
314static void
315receive_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 */
364static size_t
365transmit_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 */
397struct GNUNET_TESTBED_BarrierWaitHandle *
398GNUNET_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 */
453void
454GNUNET_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 */