aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/testbed/testbed_api.c209
-rw-r--r--src/testbed/testbed_api.h53
-rw-r--r--src/testbed/testbed_api_hosts.c10
-rw-r--r--src/testbed/testbed_api_peers.c53
4 files changed, 229 insertions, 96 deletions
diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c
index 49be33496..c691826f9 100644
--- a/src/testbed/testbed_api.c
+++ b/src/testbed/testbed_api.c
@@ -250,24 +250,108 @@ exop_check (const struct GNUNET_TESTBED_Operation *const op)
250 250
251 251
252/** 252/**
253 * Context information to be used while searching for operation contexts
254 */
255struct SearchContext
256{
257 /**
258 * The result of the search
259 */
260 struct OperationContext *opc;
261
262 /**
263 * The id of the operation context we are searching for
264 */
265 uint64_t id;
266};
267
268
269/**
270 * Search iterator for searching an operation context
271 *
272 * @param cls the serach context
273 * @param key current key code
274 * @param value value in the hash map
275 * @return GNUNET_YES if we should continue to
276 * iterate,
277 * GNUNET_NO if not.
278 */
279static int
280opc_search_iterator (void *cls, uint32_t key, void *value)
281{
282 struct SearchContext *sc = cls;
283 struct OperationContext *opc = value;
284
285 GNUNET_assert (NULL != opc);
286 GNUNET_assert (NULL == sc->opc);
287 if (opc->id != sc->id)
288 return GNUNET_YES;
289 sc->opc = opc;
290 return GNUNET_NO;
291}
292
293
294/**
253 * Returns the operation context with the given id if found in the Operation 295 * Returns the operation context with the given id if found in the Operation
254 * context queues of the controller 296 * context queues of the controller
255 * 297 *
256 * @param c the controller whose queues are searched 298 * @param c the controller whose operation context map is searched
257 * @param id the id which has to be checked 299 * @param id the id which has to be checked
258 * @return the matching operation context; NULL if no match found 300 * @return the matching operation context; NULL if no match found
259 */ 301 */
260static struct OperationContext * 302static struct OperationContext *
261find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id) 303find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
262{ 304{
263 struct OperationContext *opc; 305 struct SearchContext sc;
306
307 sc.id = id;
308 sc.opc = NULL;
309 GNUNET_assert (NULL != c->opc_map);
310 if (GNUNET_SYSERR !=
311 GNUNET_CONTAINER_multihashmap32_get_multiple (c->opc_map, (uint32_t) id,
312 &opc_search_iterator, &sc))
313 return NULL;
314 return sc.opc;
315}
264 316
265 for (opc = c->ocq_head; NULL != opc; opc = opc->next) 317
266 { 318/**
267 if (id == opc->id) 319 * Inserts the given operation context into the operation context map of the
268 return opc; 320 * given controller. Creates the operation context map if one does not exist
269 } 321 * for the controller
270 return NULL; 322 *
323 * @param c the controller
324 * @param opc the operation context to be inserted
325 */
326void
327GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c,
328 struct OperationContext *opc)
329{
330 if (NULL == c->opc_map)
331 c->opc_map = GNUNET_CONTAINER_multihashmap32_create (256);
332 GNUNET_assert (GNUNET_NO == GNUNET_CONTAINER_multihashmap32_contains_value
333 (c->opc_map, (uint32_t) opc->id, opc));
334 GNUNET_CONTAINER_multihashmap32_put (c->opc_map, (uint32_t) opc->id, opc,
335 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
336}
337
338
339/**
340 * Removes the given operation context from the operation context map of the
341 * given controller
342 *
343 * @param c the controller
344 * @param opc the operation context to remove
345 */
346void
347GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c,
348 struct OperationContext *opc)
349{
350 GNUNET_assert (NULL != c->opc_map);
351 GNUNET_assert (GNUNET_YES ==
352 GNUNET_CONTAINER_multihashmap32_remove (c->opc_map,
353 (uint32_t) opc->id,
354 opc));
271} 355}
272 356
273 357
@@ -288,7 +372,7 @@ handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
288 fo_data = opc->data; 372 fo_data = opc->data;
289 if (NULL != fo_data->cc) 373 if (NULL != fo_data->cc)
290 fo_data->cc (fo_data->cc_cls, msg); 374 fo_data->cc (fo_data->cc_cls, msg);
291 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc); 375 GNUNET_TESTBED_remove_opc_ (c, opc);
292 GNUNET_free (fo_data); 376 GNUNET_free (fo_data);
293 GNUNET_free (opc); 377 GNUNET_free (opc);
294} 378}
@@ -374,7 +458,7 @@ handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
374 default: 458 default:
375 GNUNET_assert (0); 459 GNUNET_assert (0);
376 } 460 }
377 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 461 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
378 opc->state = OPC_STATE_FINISHED; 462 opc->state = OPC_STATE_FINISHED;
379 exop_insert (event.op); 463 exop_insert (event.op);
380 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED))) 464 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
@@ -442,7 +526,7 @@ handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
442 cls = data->cls; 526 cls = data->cls;
443 op = opc->op; 527 op = opc->op;
444 GNUNET_free (opc->data); 528 GNUNET_free (opc->data);
445 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 529 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
446 opc->state = OPC_STATE_FINISHED; 530 opc->state = OPC_STATE_FINISHED;
447 exop_insert (op); 531 exop_insert (op);
448 if (NULL != cb) 532 if (NULL != cb)
@@ -513,7 +597,7 @@ handle_peer_event (struct GNUNET_TESTBED_Controller *c,
513 pcc = data->pcc; 597 pcc = data->pcc;
514 pcc_cls = data->pcc_cls; 598 pcc_cls = data->pcc_cls;
515 GNUNET_free (data); 599 GNUNET_free (data);
516 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 600 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
517 opc->state = OPC_STATE_FINISHED; 601 opc->state = OPC_STATE_FINISHED;
518 exop_insert (event.op); 602 exop_insert (event.op);
519 if (0 != 603 if (0 !=
@@ -587,7 +671,7 @@ handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
587 } 671 }
588 cb = data->cb; 672 cb = data->cb;
589 cb_cls = data->cb_cls; 673 cb_cls = data->cb_cls;
590 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 674 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
591 opc->state = OPC_STATE_FINISHED; 675 opc->state = OPC_STATE_FINISHED;
592 exop_insert (event.op); 676 exop_insert (event.op);
593 if (0 != 677 if (0 !=
@@ -669,7 +753,7 @@ handle_peer_config (struct GNUNET_TESTBED_Controller *c,
669 break; 753 break;
670 } 754 }
671 opc->data = pinfo; 755 opc->data = pinfo;
672 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 756 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
673 opc->state = OPC_STATE_FINISHED; 757 opc->state = OPC_STATE_FINISHED;
674 cb (cb_cls, opc->op, pinfo, NULL); 758 cb (cb_cls, opc->op, pinfo, NULL);
675 /* We dont check whether the operation is marked as done here as the 759 /* We dont check whether the operation is marked as done here as the
@@ -710,7 +794,7 @@ handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
710 (const struct GNUNET_MessageHeader *) msg); 794 (const struct GNUNET_MessageHeader *) msg);
711 return GNUNET_YES; 795 return GNUNET_YES;
712 } 796 }
713 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 797 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
714 opc->state = OPC_STATE_FINISHED; 798 opc->state = OPC_STATE_FINISHED;
715 emsg = GNUNET_TESTBED_parse_error_string_ (msg); 799 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
716 if (NULL == emsg) 800 if (NULL == emsg)
@@ -867,7 +951,7 @@ handle_slave_config (struct GNUNET_TESTBED_Controller *c,
867 return GNUNET_YES; 951 return GNUNET_YES;
868 } 952 }
869 opc->state = OPC_STATE_FINISHED; 953 opc->state = OPC_STATE_FINISHED;
870 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 954 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
871 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) && 955 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
872 (NULL != c->cc)) 956 (NULL != c->cc))
873 { 957 {
@@ -928,7 +1012,7 @@ handle_link_controllers_result (struct GNUNET_TESTBED_Controller *c,
928 GNUNET_free (data); 1012 GNUNET_free (data);
929 opc->data = NULL; 1013 opc->data = NULL;
930 opc->state = OPC_STATE_FINISHED; 1014 opc->state = OPC_STATE_FINISHED;
931 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 1015 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
932 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; 1016 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
933 event.op = opc->op; 1017 event.op = opc->op;
934 event.op_cls = opc->op_cls; 1018 event.op_cls = opc->op_cls;
@@ -1207,8 +1291,7 @@ GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1207 dup_msg = GNUNET_malloc (msize); 1291 dup_msg = GNUNET_malloc (msize);
1208 (void) memcpy (dup_msg, msg, msize); 1292 (void) memcpy (dup_msg, msg, msize);
1209 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg); 1293 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
1210 GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail, 1294 GNUNET_TESTBED_insert_opc_ (controller, opc);
1211 opc);
1212 return opc; 1295 return opc;
1213} 1296}
1214 1297
@@ -1222,7 +1305,7 @@ GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1222void 1305void
1223GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc) 1306GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1224{ 1307{
1225 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 1308 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1226 GNUNET_free (opc->data); 1309 GNUNET_free (opc->data);
1227 GNUNET_free (opc); 1310 GNUNET_free (opc);
1228} 1311}
@@ -1246,7 +1329,7 @@ opstart_link_controllers (void *cls)
1246 msg = data->msg; 1329 msg = data->msg;
1247 data->msg = NULL; 1330 data->msg = NULL;
1248 opc->state = OPC_STATE_STARTED; 1331 opc->state = OPC_STATE_STARTED;
1249 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc); 1332 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1250 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); 1333 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1251} 1334}
1252 1335
@@ -1269,7 +1352,7 @@ oprelease_link_controllers (void *cls)
1269 GNUNET_free (data->msg); 1352 GNUNET_free (data->msg);
1270 break; 1353 break;
1271 case OPC_STATE_STARTED: 1354 case OPC_STATE_STARTED:
1272 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 1355 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1273 break; 1356 break;
1274 case OPC_STATE_FINISHED: 1357 case OPC_STATE_FINISHED:
1275 break; 1358 break;
@@ -1296,7 +1379,7 @@ opstart_get_slave_config (void *cls)
1296 GNUNET_free (opc->data); 1379 GNUNET_free (opc->data);
1297 data = NULL; 1380 data = NULL;
1298 opc->data = NULL; 1381 opc->data = NULL;
1299 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc); 1382 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1300 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); 1383 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1301 opc->state = OPC_STATE_STARTED; 1384 opc->state = OPC_STATE_STARTED;
1302} 1385}
@@ -1318,7 +1401,7 @@ oprelease_get_slave_config (void *cls)
1318 GNUNET_free (opc->data); 1401 GNUNET_free (opc->data);
1319 break; 1402 break;
1320 case OPC_STATE_STARTED: 1403 case OPC_STATE_STARTED:
1321 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 1404 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1322 break; 1405 break;
1323 case OPC_STATE_FINISHED: 1406 case OPC_STATE_FINISHED:
1324 if (NULL != opc->data) 1407 if (NULL != opc->data)
@@ -1465,37 +1548,71 @@ GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1465 1548
1466 1549
1467/** 1550/**
1551 * Iterator to free opc map entries
1552 *
1553 * @param cls closure
1554 * @param key current key code
1555 * @param value value in the hash map
1556 * @return GNUNET_YES if we should continue to
1557 * iterate,
1558 * GNUNET_NO if not.
1559 */
1560static int
1561opc_free_iterator (void *cls, uint32_t key, void *value)
1562{
1563 struct GNUNET_CONTAINER_MultiHashMap32 *map = cls;
1564 struct OperationContext *opc = value;
1565
1566 GNUNET_assert (NULL != opc);
1567 GNUNET_break (0);
1568 GNUNET_free (opc);
1569 GNUNET_assert (GNUNET_YES ==
1570 GNUNET_CONTAINER_multihashmap32_remove (map, key, value));
1571 return GNUNET_YES;
1572}
1573
1574
1575/**
1468 * disconnects from the controller. 1576 * disconnects from the controller.
1469 * 1577 *
1470 * @param controller handle to controller to stop 1578 * @param c handle to controller to stop
1471 */ 1579 */
1472void 1580void
1473GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller 1581GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1474 *controller) 1582 *c)
1475{ 1583{
1476 struct MessageQueue *mq_entry; 1584 struct MessageQueue *mq_entry;
1477 1585
1478 if (NULL != controller->th) 1586 if (NULL != c->th)
1479 GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th); 1587 GNUNET_CLIENT_notify_transmit_ready_cancel (c->th);
1480 /* Clear the message queue */ 1588 /* Clear the message queue */
1481 while (NULL != (mq_entry = controller->mq_head)) 1589 while (NULL != (mq_entry = c->mq_head))
1482 { 1590 {
1483 GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail, 1591 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail,
1484 mq_entry); 1592 mq_entry);
1485 GNUNET_free (mq_entry->msg); 1593 GNUNET_free (mq_entry->msg);
1486 GNUNET_free (mq_entry); 1594 GNUNET_free (mq_entry);
1487 } 1595 }
1488 if (NULL != controller->client) 1596 if (NULL != c->client)
1489 GNUNET_CLIENT_disconnect (controller->client); 1597 GNUNET_CLIENT_disconnect (c->client);
1490 if (NULL != controller->host) 1598 if (NULL != c->host)
1491 GNUNET_TESTBED_deregister_host_at_ (controller->host, controller); 1599 GNUNET_TESTBED_deregister_host_at_ (c->host, c);
1492 GNUNET_CONFIGURATION_destroy (controller->cfg); 1600 GNUNET_CONFIGURATION_destroy (c->cfg);
1493 GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations); 1601 GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_operations);
1494 GNUNET_TESTBED_operation_queue_destroy_ 1602 GNUNET_TESTBED_operation_queue_destroy_
1495 (controller->opq_parallel_service_connections); 1603 (c->opq_parallel_service_connections);
1496 GNUNET_TESTBED_operation_queue_destroy_ 1604 GNUNET_TESTBED_operation_queue_destroy_
1497 (controller->opq_parallel_topology_config_operations); 1605 (c->opq_parallel_topology_config_operations);
1498 GNUNET_free (controller); 1606 if (NULL != c->opc_map)
1607 {
1608 GNUNET_assert (GNUNET_SYSERR !=
1609 GNUNET_CONTAINER_multihashmap32_iterate (c->opc_map,
1610 &opc_free_iterator,
1611 c->opc_map));
1612 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map));
1613 GNUNET_CONTAINER_multihashmap32_destroy (c->opc_map);
1614 }
1615 GNUNET_free (c);
1499} 1616}
1500 1617
1501 1618
@@ -1951,7 +2068,7 @@ opstart_shutdown_peers (void *cls)
1951 htons (sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)); 2068 htons (sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage));
1952 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS); 2069 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS);
1953 msg->operation_id = GNUNET_htonll (opc->id); 2070 msg->operation_id = GNUNET_htonll (opc->id);
1954 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc); 2071 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1955 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); 2072 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1956} 2073}
1957 2074
@@ -1969,7 +2086,7 @@ oprelease_shutdown_peers (void *cls)
1969 switch (opc->state) 2086 switch (opc->state)
1970 { 2087 {
1971 case OPC_STATE_STARTED: 2088 case OPC_STATE_STARTED:
1972 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 2089 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1973 /* no break; continue */ 2090 /* no break; continue */
1974 case OPC_STATE_INIT: 2091 case OPC_STATE_INIT:
1975 GNUNET_free (opc->data); 2092 GNUNET_free (opc->data);
@@ -1989,7 +2106,7 @@ oprelease_shutdown_peers (void *cls)
1989 * when there are no other pending operations. If there are pending operations, 2106 * when there are no other pending operations. If there are pending operations,
1990 * it will return NULL 2107 * it will return NULL
1991 * 2108 *
1992 * @param controller the controller to send this message to 2109 * @param c the controller to send this message to
1993 * @param op_cls closure for the operation 2110 * @param op_cls closure for the operation
1994 * @param cb the callback to call when all peers are stopped and destroyed 2111 * @param cb the callback to call when all peers are stopped and destroyed
1995 * @param cb_cls the closure for the callback 2112 * @param cb_cls the closure for the callback
@@ -1997,7 +2114,7 @@ oprelease_shutdown_peers (void *cls)
1997 * present 2114 * present
1998 */ 2115 */
1999struct GNUNET_TESTBED_Operation * 2116struct GNUNET_TESTBED_Operation *
2000GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *controller, 2117GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *c,
2001 void *op_cls, 2118 void *op_cls,
2002 GNUNET_TESTBED_OperationCompletionCallback cb, 2119 GNUNET_TESTBED_OperationCompletionCallback cb,
2003 void *cb_cls) 2120 void *cb_cls)
@@ -2005,16 +2122,16 @@ GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *controller,
2005 struct OperationContext *opc; 2122 struct OperationContext *opc;
2006 struct ShutdownPeersData *data; 2123 struct ShutdownPeersData *data;
2007 2124
2008 if (NULL != controller->ocq_head) 2125 if (0 != GNUNET_CONTAINER_multihashmap32_size (c->opc_map))
2009 return NULL; 2126 return NULL;
2010 data = GNUNET_malloc (sizeof (struct ShutdownPeersData)); 2127 data = GNUNET_malloc (sizeof (struct ShutdownPeersData));
2011 data->cb = cb; 2128 data->cb = cb;
2012 data->cb_cls = cb_cls; 2129 data->cb_cls = cb_cls;
2013 opc = GNUNET_malloc (sizeof (struct OperationContext)); 2130 opc = GNUNET_malloc (sizeof (struct OperationContext));
2014 opc->c = controller; 2131 opc->c = c;
2015 opc->op_cls = op_cls; 2132 opc->op_cls = op_cls;
2016 opc->data = data; 2133 opc->data = data;
2017 opc->id = GNUNET_TESTBED_get_next_op_id (controller); 2134 opc->id = GNUNET_TESTBED_get_next_op_id (c);
2018 opc->type = OP_SHUTDOWN_PEERS; 2135 opc->type = OP_SHUTDOWN_PEERS;
2019 opc->state = OPC_STATE_INIT; 2136 opc->state = OPC_STATE_INIT;
2020 opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_shutdown_peers, 2137 opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_shutdown_peers,
diff --git a/src/testbed/testbed_api.h b/src/testbed/testbed_api.h
index 7c7edff5f..320289bb0 100644
--- a/src/testbed/testbed_api.h
+++ b/src/testbed/testbed_api.h
@@ -136,16 +136,6 @@ enum OperationContextState
136struct OperationContext 136struct OperationContext
137{ 137{
138 /** 138 /**
139 * next ptr for DLL
140 */
141 struct OperationContext *next;
142
143 /**
144 * prev ptr for DLL
145 */
146 struct OperationContext *prev;
147
148 /**
149 * The controller to which this operation context belongs to 139 * The controller to which this operation context belongs to
150 */ 140 */
151 struct GNUNET_TESTBED_Controller *c; 141 struct GNUNET_TESTBED_Controller *c;
@@ -240,14 +230,9 @@ struct GNUNET_TESTBED_Controller
240 struct GNUNET_TESTBED_HostRegistrationHandle *rh; 230 struct GNUNET_TESTBED_HostRegistrationHandle *rh;
241 231
242 /** 232 /**
243 * The head of the opeartion context queue 233 * The map of active operation contexts
244 */
245 struct OperationContext *ocq_head;
246
247 /**
248 * The tail of the operation context queue
249 */ 234 */
250 struct OperationContext *ocq_tail; 235 struct GNUNET_CONTAINER_MultiHashMap32 *opc_map;
251 236
252 /** 237 /**
253 * Operation queue for simultaneous operations 238 * Operation queue for simultaneous operations
@@ -294,6 +279,31 @@ GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
294 279
295 280
296/** 281/**
282 * Inserts the given operation context into the operation context map of the
283 * given controller. Creates the operation context map if one does not exist
284 * for the controller
285 *
286 * @param c the controller
287 * @param opc the operation context to be inserted
288 */
289void
290GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c,
291 struct OperationContext *opc);
292
293
294/**
295 * Removes the given operation context from the operation context map of the
296 * given controller
297 *
298 * @param c the controller
299 * @param opc the operation context to remove
300 */
301void
302GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c,
303 struct OperationContext *opc);
304
305
306/**
297 * Compresses given configuration using zlib compress 307 * Compresses given configuration using zlib compress
298 * 308 *
299 * @param config the serialized configuration 309 * @param config the serialized configuration
@@ -322,15 +332,6 @@ GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg,
322 332
323 333
324/** 334/**
325 * Adds an operation to the queue of operations
326 *
327 * @param op the operation to add
328 */
329void
330GNUNET_TESTBED_operation_add_ (struct GNUNET_TESTBED_Operation *op);
331
332
333/**
334 * Creates a helper initialization message. This function is here because we 335 * Creates a helper initialization message. This function is here because we
335 * want to use this in testing 336 * want to use this in testing
336 * 337 *
diff --git a/src/testbed/testbed_api_hosts.c b/src/testbed/testbed_api_hosts.c
index 0774c023e..f61129b85 100644
--- a/src/testbed/testbed_api_hosts.c
+++ b/src/testbed/testbed_api_hosts.c
@@ -127,16 +127,6 @@ struct GNUNET_TESTBED_Host
127{ 127{
128 128
129 /** 129 /**
130 * The next pointer for DLL
131 */
132 struct GNUNET_TESTBED_Host *next;
133
134 /**
135 * The prev pointer for DLL
136 */
137 struct GNUNET_TESTBED_Host *prev;
138
139 /**
140 * The hostname of the host; NULL for localhost 130 * The hostname of the host; NULL for localhost
141 */ 131 */
142 const char *hostname; 132 const char *hostname;
diff --git a/src/testbed/testbed_api_peers.c b/src/testbed/testbed_api_peers.c
index fe3fad601..8341a96a3 100644
--- a/src/testbed/testbed_api_peers.c
+++ b/src/testbed/testbed_api_peers.c
@@ -121,7 +121,7 @@ opstart_peer_create (void *cls)
121 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->peer->host)); 121 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->peer->host));
122 msg->peer_id = htonl (data->peer->unique_id); 122 msg->peer_id = htonl (data->peer->unique_id);
123 msg->config_size = htonl (c_size); 123 msg->config_size = htonl (c_size);
124 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc); 124 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
125 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); 125 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
126} 126}
127 127
@@ -139,7 +139,7 @@ oprelease_peer_create (void *cls)
139 switch (opc->state) 139 switch (opc->state)
140 { 140 {
141 case OPC_STATE_STARTED: 141 case OPC_STATE_STARTED:
142 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 142 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
143 /* No break we continue flow */ 143 /* No break we continue flow */
144 case OPC_STATE_INIT: 144 case OPC_STATE_INIT:
145 GNUNET_free (((struct PeerCreateData *) opc->data)->peer); 145 GNUNET_free (((struct PeerCreateData *) opc->data)->peer);
@@ -172,7 +172,7 @@ opstart_peer_destroy (void *cls)
172 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER); 172 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER);
173 msg->peer_id = htonl (peer->unique_id); 173 msg->peer_id = htonl (peer->unique_id);
174 msg->operation_id = GNUNET_htonll (opc->id); 174 msg->operation_id = GNUNET_htonll (opc->id);
175 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc); 175 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
176 GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header); 176 GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header);
177} 177}
178 178
@@ -190,7 +190,7 @@ oprelease_peer_destroy (void *cls)
190 switch (opc->state) 190 switch (opc->state)
191 { 191 {
192 case OPC_STATE_STARTED: 192 case OPC_STATE_STARTED:
193 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 193 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
194 /* no break; continue */ 194 /* no break; continue */
195 case OPC_STATE_INIT: 195 case OPC_STATE_INIT:
196 break; 196 break;
@@ -224,7 +224,7 @@ opstart_peer_start (void *cls)
224 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_START_PEER); 224 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_START_PEER);
225 msg->peer_id = htonl (peer->unique_id); 225 msg->peer_id = htonl (peer->unique_id);
226 msg->operation_id = GNUNET_htonll (opc->id); 226 msg->operation_id = GNUNET_htonll (opc->id);
227 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc); 227 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
228 GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header); 228 GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header);
229} 229}
230 230
@@ -242,7 +242,7 @@ oprelease_peer_start (void *cls)
242 switch (opc->state) 242 switch (opc->state)
243 { 243 {
244 case OPC_STATE_STARTED: 244 case OPC_STATE_STARTED:
245 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 245 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
246 /* no break; continue */ 246 /* no break; continue */
247 case OPC_STATE_INIT: 247 case OPC_STATE_INIT:
248 GNUNET_free (opc->data); 248 GNUNET_free (opc->data);
@@ -276,7 +276,7 @@ opstart_peer_stop (void *cls)
276 msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerStopMessage)); 276 msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerStopMessage));
277 msg->peer_id = htonl (peer->unique_id); 277 msg->peer_id = htonl (peer->unique_id);
278 msg->operation_id = GNUNET_htonll (opc->id); 278 msg->operation_id = GNUNET_htonll (opc->id);
279 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc); 279 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
280 GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header); 280 GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header);
281} 281}
282 282
@@ -294,7 +294,7 @@ oprelease_peer_stop (void *cls)
294 switch (opc->state) 294 switch (opc->state)
295 { 295 {
296 case OPC_STATE_STARTED: 296 case OPC_STATE_STARTED:
297 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 297 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
298 /* no break; continue */ 298 /* no break; continue */
299 case OPC_STATE_INIT: 299 case OPC_STATE_INIT:
300 GNUNET_free (opc->data); 300 GNUNET_free (opc->data);
@@ -349,7 +349,7 @@ opstart_peer_getinfo (void *cls)
349 msg = 349 msg =
350 GNUNET_TESTBED_generate_peergetconfig_msg_ (data->peer->unique_id, 350 GNUNET_TESTBED_generate_peergetconfig_msg_ (data->peer->unique_id,
351 opc->id); 351 opc->id);
352 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc); 352 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
353 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); 353 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
354} 354}
355 355
@@ -368,7 +368,7 @@ oprelease_peer_getinfo (void *cls)
368 switch (opc->state) 368 switch (opc->state)
369 { 369 {
370 case OPC_STATE_STARTED: 370 case OPC_STATE_STARTED:
371 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 371 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
372 /* no break; continue */ 372 /* no break; continue */
373 case OPC_STATE_INIT: 373 case OPC_STATE_INIT:
374 GNUNET_free (opc->data); 374 GNUNET_free (opc->data);
@@ -419,7 +419,7 @@ opstart_overlay_connect (void *cls)
419 msg->peer2 = htonl (data->p2->unique_id); 419 msg->peer2 = htonl (data->p2->unique_id);
420 msg->operation_id = GNUNET_htonll (opc->id); 420 msg->operation_id = GNUNET_htonll (opc->id);
421 msg->peer2_host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->p2->host)); 421 msg->peer2_host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->p2->host));
422 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc); 422 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
423 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); 423 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
424} 424}
425 425
@@ -444,7 +444,7 @@ oprelease_overlay_connect (void *cls)
444 case OPC_STATE_STARTED: 444 case OPC_STATE_STARTED:
445 (void) GNUNET_TESTBED_release_time_slot_ (data->p1->host, data->tslot_index, 445 (void) GNUNET_TESTBED_release_time_slot_ (data->p1->host, data->tslot_index,
446 data); 446 data);
447 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 447 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
448 break; 448 break;
449 case OPC_STATE_FINISHED: 449 case OPC_STATE_FINISHED:
450 duration = GNUNET_TIME_absolute_get_duration (data->tstart); 450 duration = GNUNET_TIME_absolute_get_duration (data->tstart);
@@ -774,6 +774,11 @@ GNUNET_TESTBED_overlay_connect (void *op_cls,
774} 774}
775 775
776 776
777/**
778 * Function called when a peer manage service operation is ready
779 *
780 * @param cls the closure from GNUNET_TESTBED_operation_create_()
781 */
777static void 782static void
778opstart_manage_service (void *cls) 783opstart_manage_service (void *cls)
779{ 784{
@@ -793,11 +798,16 @@ opstart_manage_service (void *cls)
793 GNUNET_free (data->service_name); 798 GNUNET_free (data->service_name);
794 data->service_name = NULL; 799 data->service_name = NULL;
795 opc->state = OPC_STATE_STARTED; 800 opc->state = OPC_STATE_STARTED;
796 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc); 801 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
797 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); 802 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
798} 803}
799 804
800 805
806/**
807 * Callback which will be called when peer manage server operation is released
808 *
809 * @param cls the closure from GNUNET_TESTBED_operation_create_()
810 */
801static void 811static void
802oprelease_manage_service (void *cls) 812oprelease_manage_service (void *cls)
803{ 813{
@@ -808,7 +818,7 @@ oprelease_manage_service (void *cls)
808 switch (opc->state) 818 switch (opc->state)
809 { 819 {
810 case OPC_STATE_STARTED: 820 case OPC_STATE_STARTED:
811 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc); 821 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
812 break; 822 break;
813 case OPC_STATE_INIT: 823 case OPC_STATE_INIT:
814 GNUNET_assert (NULL != data); 824 GNUNET_assert (NULL != data);
@@ -822,6 +832,21 @@ oprelease_manage_service (void *cls)
822} 832}
823 833
824 834
835/**
836 * Start or stop given service at a peer. This should not be called to
837 * start/stop the peer's ARM service. Use GNUNET_TESTBED_peer_start(),
838 * GNUNET_TESTBED_peer_stop() for starting/stopping peer's ARM service. Success
839 * or failure of the generated operation is signalled through the controller
840 * event callback and/or operation completion callback.
841 *
842 * @param op_cls the closure for the operation
843 * @param peer the peer whose service is to be started/stopped
844 * @param service_name the name of the service
845 * @param cb the operation completion callback
846 * @param cb_cls the closure for the operation completion callback
847 * @param start 1 to start the service; 0 to stop the service
848 * @return an operation handle; NULL upon error (peer not running)
849 */
825struct GNUNET_TESTBED_Operation * 850struct GNUNET_TESTBED_Operation *
826GNUNET_TESTBED_peer_manage_service (void *op_cls, 851GNUNET_TESTBED_peer_manage_service (void *op_cls,
827 struct GNUNET_TESTBED_Peer *peer, 852 struct GNUNET_TESTBED_Peer *peer,