* @param event information about the event
*/
typedef void (*GNUNET_TESTBED_ControllerCallback)(void *cls,
- const struct GNUNET_TESTBED_EventInformation *event);
+ const struct GNUNET_TESTBED_EventInformation *event);
/**
- * Start a controller process using the given configuration at the
+ * Opaque Handle for Controller process
+ */
+struct GNUNET_TESTBED_ControllerProc;
+
+
+/**
+ * Starts a controller process at the host
+ *
+ * @param host the host where the controller has to be started; NULL for localhost
+ * @return the controller process handle
+ */
+struct GNUNET_TESTBED_ControllerProc *
+GNUNET_TESTBED_controller_start (struct GNUNET_TESTBED_Host *host);
+
+
+/**
+ * Stop the controller process (also will terminate all peers and controllers
+ * dependent on this controller). This function blocks until the testbed has
+ * been fully terminated (!).
+ *
+ * @param cproc the controller process handle
+ */
+void
+GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc);
+
+
+/**
+ * Connect to a controller process using the given configuration at the
* given host.
*
* @param cfg configuration to use
- * @param host host to run the controller on, NULL for 'localhost'
+ * @param host host to run the controller on; This should be the same host if
+ * the controller was previously started with
+ * GNUNET_TESTBED_controller_start; NULL for localhost
+ * @param host host where this controller is being run;
* @param event_mask bit mask with set of events to call 'cc' for;
* or-ed values of "1LL" shifted by the
* respective 'enum GNUNET_TESTBED_EventType'
* @return handle to the controller
*/
struct GNUNET_TESTBED_Controller *
-GNUNET_TESTBED_controller_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
- struct GNUNET_TESTBED_Host *host,
- uint64_t event_mask,
- GNUNET_TESTBED_ControllerCallback cc,
- void *cc_cls);
+GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ struct GNUNET_TESTBED_Host *host,
+ uint64_t event_mask,
+ GNUNET_TESTBED_ControllerCallback cc,
+ void *cc_cls);
/**
* @param controller handle to controller to stop
*/
void
-GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_Controller *controller);
+GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller *controller);
/**
* host
*/
struct GNUNET_TESTBED_Controller *fcontroller;
+
+ /**
+ * The controller process handle if we started the controller
+ */
+ struct GNUNET_TESTBED_ControllerProc *fcontroller_proc;
};
host_list[lcf->slave_host_id],
lcf->cfg, lcf->is_subordinate);
lcf->state = FINISHED;
- break;
case FINISHED:
lcfq = lcfq_head;
GNUNET_CONFIGURATION_destroy (lcfq->lcf->cfg);
return;
}
GNUNET_assert (config_size == dest_size);
- cfg = GNUNET_CONFIGURATION_create ();
+ cfg = GNUNET_CONFIGURATION_create (); /* Free here or in lcfcontext */
if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, config_size,
GNUNET_NO))
{
GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
+ }
+ else
+ {
+
}
GNUNET_SERVER_receive_done (client, GNUNET_OK);
/* If we are not the slave controller then we have to route the request
if (NULL != route_list[route_id])
{
if (NULL != route_list[route_id]->fcontroller)
- GNUNET_TESTBED_controller_stop (route_list[route_id]->fcontroller);
+ GNUNET_TESTBED_controller_disconnect (route_list[route_id]->fcontroller);
+ if (NULL != route_list[route_id]->fcontroller_proc)
+ GNUNET_TESTBED_controller_stop (route_list[route_id]->fcontroller_proc);
GNUNET_free (route_list[route_id]);
}
GNUNET_free_non_null (route_list);
/**
* The host where the controller is running
*/
- const struct GNUNET_TESTBED_Host *host;
-
- /**
- * The helper handle
- */
- struct GNUNET_TESTBED_HelperHandle *helper;
+ struct GNUNET_TESTBED_Host *host;
/**
* The controller callback
* Did we start the receive loop yet?
*/
int in_receive;
+
+ /**
+ * Did we create the host for this?
+ */
+ int aux_host;
};
}
+/**
+ * Handle for controller process
+ */
+struct GNUNET_TESTBED_ControllerProc
+{
+ /**
+ * The helper handle
+ */
+ struct GNUNET_TESTBED_HelperHandle *helper;
+
+};
+
+
+/**
+ * Starts a controller process at the host
+ *
+ * @param host the host where the controller has to be started; NULL for localhost
+ * @return the controller process handle
+ */
+struct GNUNET_TESTBED_ControllerProc *
+GNUNET_TESTBED_controller_start (struct GNUNET_TESTBED_Host *host)
+{
+ struct GNUNET_TESTBED_ControllerProc *cproc;
+ char * const binary_argv[] = {
+ "gnunet-service-testbed",
+ "gnunet-service-testbed",
+ NULL
+ };
+
+ cproc = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ControllerProc));
+ cproc->helper = GNUNET_TESTBED_host_run_ (host, binary_argv);
+ if (NULL == cproc->helper)
+ {
+ GNUNET_free (cproc);
+ return NULL;
+ }
+ return cproc;
+}
+
+
+/**
+ * Stop the controller process (also will terminate all peers and controllers
+ * dependent on this controller). This function blocks until the testbed has
+ * been fully terminated (!).
+ *
+ * @param cproc the controller process handle
+ */
+void
+GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc)
+{
+ GNUNET_TESTBED_host_stop_ (cproc->helper);
+ GNUNET_free (cproc);
+}
+
+
/**
* Start a controller process using the given configuration at the
* given host.
*
* @param cfg configuration to use
- * @param host host to run the controller on, NULL for 'localhost'
+ * @param host host to run the controller on; This should be the same host if
+ * the controller was previously started with
+ * GNUNET_TESTBED_controller_start; NULL for localhost
* @param event_mask bit mask with set of events to call 'cc' for;
* or-ed values of "1LL" shifted by the
* respective 'enum GNUNET_TESTBED_EventType'
* @return handle to the controller
*/
struct GNUNET_TESTBED_Controller *
-GNUNET_TESTBED_controller_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
- struct GNUNET_TESTBED_Host *host,
- uint64_t event_mask,
- GNUNET_TESTBED_ControllerCallback cc,
- void *cc_cls)
+GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ struct GNUNET_TESTBED_Host *host,
+ uint64_t event_mask,
+ GNUNET_TESTBED_ControllerCallback cc,
+ void *cc_cls)
{
struct GNUNET_TESTBED_Controller *controller;
- char * const binary_argv[] = {
- "gnunet-service-testbed",
- "gnunet-service-testbed",
- NULL
- };
struct GNUNET_TESTBED_InitMessage *msg;
controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
- controller->helper = GNUNET_TESTBED_host_run_ (host, binary_argv);
- if (NULL == controller->helper)
- {
- GNUNET_free (controller);
- return NULL;
- }
- controller->host = host;
controller->cc = cc;
controller->cc_cls = cc_cls;
controller->event_mask = event_mask;
controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
- controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
+ controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
if (NULL == controller->client)
{
- GNUNET_TESTBED_controller_stop (controller);
+ GNUNET_TESTBED_controller_disconnect (controller);
return NULL;
- }
+ }
+ if (NULL == host)
+ {
+ host = GNUNET_TESTBED_host_create_by_id_ (0);
+ if (NULL == host)
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Treating NULL host as localhost. Multiple references to localhost. "
+ " May break when localhost freed before calling disconnect \n");
+ host = GNUNET_TESTBED_host_lookup_by_id_ (0);
+ }
+ else
+ {
+ controller->aux_host = GNUNET_YES;
+ }
+ }
+ GNUNET_assert (NULL != host);
msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage));
msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
msg->header.size = htons (sizeof (struct GNUNET_TESTBED_InitMessage));
- msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
+ msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
msg->event_mask = GNUNET_htonll (controller->event_mask);
queue_message (controller, (struct GNUNET_MessageHeader *) msg);
return controller;
/**
- * Stop the given controller (also will terminate all peers and
- * controllers dependent on this controller). This function
- * blocks until the testbed has been fully terminated (!).
+ * disconnects from the controller.
*
* @param controller handle to controller to stop
*/
void
-GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_Controller *controller)
+GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller *controller)
{
struct MessageQueue *mq_entry;
}
if (NULL != controller->client)
GNUNET_CLIENT_disconnect (controller->client);
- GNUNET_TESTBED_host_stop_ (controller->helper);
GNUNET_CONFIGURATION_destroy (controller->cfg);
+ if (GNUNET_YES == controller->aux_host)
+ GNUNET_TESTBED_host_destroy (controller->host);
GNUNET_free (controller);
}
#include "gnunet_hello_lib.h"
#include "gnunet_container_lib.h"
+/**
+ * Generic logging shorthand
+ */
+#define LOG(kind, ...) \
+ GNUNET_log_from (kind, "testbed-api-hosts", __VA_ARGS__);
+
+/**
+ * Number of extra elements we create space for when we grow host list
+ */
+#define HOST_LIST_GROW_STEP 10
+
+
/**
* A list entry for registered controllers list
*/
struct RegisteredController *prev;
};
+
/**
* Opaque handle to a host running experiments managed by the testing framework.
* The master process must be able to SSH to this host without password (via
/**
* Global ID we use to refer to a host on the network
*/
- uint32_t unique_id;
+ uint32_t id;
/**
* The port which is to be used for SSH
/**
- * Head element in the list of available hosts
+ * Array of available hosts
*/
-static struct GNUNET_TESTBED_Host *host_list_head;
+static struct GNUNET_TESTBED_Host **host_list;
/**
- * Tail element in the list of available hosts
+ * The size of the available hosts list
*/
-static struct GNUNET_TESTBED_Host *host_list_tail;
+static uint32_t host_list_size;
/**
struct GNUNET_TESTBED_Host *
GNUNET_TESTBED_host_lookup_by_id_ (uint32_t id)
{
- struct GNUNET_TESTBED_Host *host;
-
- for (host = host_list_head; NULL != host; host=host->next)
- if (id == host->unique_id)
- return host;
- return NULL;
+ if (host_list_size <= id)
+ return NULL;
+ return host_list[id];
}
struct GNUNET_TESTBED_Host *
GNUNET_TESTBED_host_create_by_id_ (uint32_t id)
{
- struct GNUNET_TESTBED_Host *host;
-
- host = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Host));
- host->unique_id = id;
- return host;
+ return GNUNET_TESTBED_host_create_with_id (id, NULL, NULL, 0);
}
uint32_t
GNUNET_TESTBED_host_get_id_ (const struct GNUNET_TESTBED_Host *host)
{
- return host->unique_id;
+ return host->id;
}
{
struct GNUNET_TESTBED_Host *host;
+ if ((id < host_list_size) && (NULL != host_list[host_list_size]))
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING, "Host with id: %u already created\n");
+ return NULL;
+ }
host = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Host));
host->hostname = hostname;
host->username = username;
- host->unique_id = id;
+ host->id = id;
host->port = (0 == port) ? 22 : port;
- GNUNET_CONTAINER_DLL_insert_tail (host_list_head, host_list_tail, host);
+ if (id < host_list_size)
+ {
+ host_list_size += HOST_LIST_GROW_STEP;
+ host_list = GNUNET_realloc (host_list, sizeof (struct GNUNET_TESTBED_Host)
+ * host_list_size);
+ }
+ host_list[id] = host;
return host;
}
GNUNET_TESTBED_host_destroy (struct GNUNET_TESTBED_Host *host)
{
struct RegisteredController *rc;
-
- GNUNET_CONTAINER_DLL_remove (host_list_head, host_list_tail, host);
+ uint32_t id;
+
+ GNUNET_assert (host->id < host_list_size);
+ GNUNET_assert (host_list[host->id] == host);
+ host_list[host->id] = NULL;
/* clear registered controllers list */
for (rc=host->rc_head; NULL != rc; rc=host->rc_head)
{
GNUNET_CONTAINER_DLL_remove (host->rc_head, host->rc_tail, rc);
GNUNET_free (rc);
}
+ for (id = 0; id < HOST_LIST_GROW_STEP; id++)
+ {
+ if ((host->id + id >= host_list_size) || (NULL != host_list[host->id + id]))
+ break;
+ }
+ if (HOST_LIST_GROW_STEP == id)
+ {
+ host_list_size -= HOST_LIST_GROW_STEP;
+ host_list = GNUNET_realloc (host_list, host_list_size);
+ }
GNUNET_free (host);
}
argc++;
h = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_HelperHandle));
h->cpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_YES, GNUNET_NO);
- if (0 == host->unique_id)
+ if ((NULL == host) || (0 == host->id))
{
h->process = GNUNET_OS_start_process_vap (GNUNET_YES,
h->cpipe, NULL,
binary_argv);
}
else
- {
+ {
char *remote_args[argc + 6 + 1];
unsigned int argp;