/*
This file is part of GNUnet.
- (C) 2008--2013 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2008--2013 GNUnet e.V.
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
*/
/**
* @file testbed/gnunet-service-testbed_peers.c
* @brief implementation of TESTBED service that deals with peer management
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
*/
#include "gnunet-service-testbed.h"
*/
struct Peer **GST_peer_list;
+/**
+ * The current number of peers running locally under this controller
+ */
+unsigned int GST_num_local_peers;
+
/**
* Context information to manage peers' services
* The client which requested to manage the peer's service
*/
struct GNUNET_SERVER_Client *client;
-
+
/**
* The operation id of the associated request
*/
uint64_t op_id;
-
+
/**
* 1 if the service at the peer has to be started; 0 if it has to be stopped
*/
* Is this context expired? Do not work on this context if it is set to
* GNUNET_YES
*/
- uint8_t expired;
+ uint8_t expired;
};
GST_array_grow_large_enough (GST_peer_list, GST_peer_list_size, peer->id);
GNUNET_assert (NULL == GST_peer_list[peer->id]);
GST_peer_list[peer->id] = peer;
+ if (GNUNET_NO == peer->is_remote)
+ GST_num_local_peers++;
}
unsigned int orig_size;
uint32_t id;
+ if (GNUNET_NO == peer->is_remote)
+ GST_num_local_peers--;
GST_peer_list[peer->id] = NULL;
orig_size = GST_peer_list_size;
while (GST_peer_list_size >= LIST_GROW_STEP)
* timed out
*
* @param cls the FowardedOperationContext
- * @param tc the TaskContext from the scheduler
*/
static void
-peer_create_forward_timeout (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+peer_create_forward_timeout (void *cls)
{
struct ForwardedOperationContext *fopc = cls;
GNUNET_free (fopc->cls);
- GST_forwarded_operation_timeout (fopc, tc);
+ GST_forwarded_operation_timeout (fopc);
}
return;
}
if (UINT32_MAX == peer_id)
- {
+ {
GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
"Cannot create peer with given ID");
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
GNUNET_CONFIGURATION_set_value_number (cfg, "TESTBED", "PEERID",
(unsigned long long) peer_id);
- peer = GNUNET_malloc (sizeof (struct Peer));
+
+ GNUNET_CONFIGURATION_set_value_number (cfg, "PATHS", "PEERID",
+ (unsigned long long) peer_id);
+ peer = GNUNET_new (struct Peer);
peer->is_remote = GNUNET_NO;
peer->details.local.cfg = cfg;
peer->id = peer_id;
}
peer->details.local.is_running = GNUNET_NO;
peer_list_add (peer);
- reply =
- GNUNET_malloc (sizeof
- (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
+ reply = GNUNET_new (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage);
reply->header.size =
htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
reply->header.type =
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
- peer = GNUNET_malloc (sizeof (struct Peer));
+ peer = GNUNET_new (struct Peer);
peer->is_remote = GNUNET_YES;
peer->id = peer_id;
peer->details.remote.slave = GST_slave_list[route->dest];
peer->details.remote.remote_host_id = host_id;
- fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
+ fo_ctxt = GNUNET_new (struct ForwardedOperationContext);
GNUNET_SERVER_client_keep (client);
fo_ctxt->client = client;
fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id);
/**
- * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
+ * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
*
* @param cls NULL
* @param client identification of the client
* @param message the actual message
*/
void
-GST_handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
+GST_handle_peer_destroy (void *cls,
+ struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message)
{
const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
peer_id = ntohl (msg->peer_id);
- LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
- peer_id, GNUNET_ntohll (msg->operation_id));
+ LOG_DEBUG ("Received peer destory on peer: %u and operation id: %llu\n",
+ (unsigned int) peer_id,
+ (unsigned long long) GNUNET_ntohll (msg->operation_id));
if (!VALID_PEER_ID (peer_id))
{
LOG (GNUNET_ERROR_TYPE_ERROR,
if (GNUNET_YES == peer->is_remote)
{
/* Forward the destory message to sub controller */
- fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
+ fopc = GNUNET_new (struct ForwardedOperationContext);
GNUNET_SERVER_client_keep (client);
fopc->client = client;
fopc->cls = peer;
* Stats a peer
*
* @param peer the peer to start
- * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
*/
static int
start_peer (struct Peer *peer)
* Stops a peer
*
* @param peer the peer to stop
- * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
*/
static int
stop_peer (struct Peer *peer)
peer = GST_peer_list[peer_id];
if (GNUNET_YES == peer->is_remote)
{
- fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
+ fopc = GNUNET_new (struct ForwardedOperationContext);
GNUNET_SERVER_client_keep (client);
fopc->client = client;
fopc->operation_id = GNUNET_ntohll (msg->operation_id);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
- reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
+ reply = GNUNET_new (struct GNUNET_TESTBED_PeerEventMessage);
reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT);
reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
{
LOG (GNUNET_ERROR_TYPE_DEBUG, "Forwarding PEER_STOP for peer %u\n",
peer_id);
- fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
+ fopc = GNUNET_new (struct ForwardedOperationContext);
GNUNET_SERVER_client_keep (client);
fopc->client = client;
fopc->operation_id = GNUNET_ntohll (msg->operation_id);
return;
}
LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %u successfully stopped\n", peer_id);
- reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
+ reply = GNUNET_new (struct GNUNET_TESTBED_PeerEventMessage);
reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT);
reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
if (GNUNET_YES == peer->is_remote)
{
LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", peer_id);
- fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
+ fopc = GNUNET_new (struct ForwardedOperationContext);
GNUNET_SERVER_client_keep (client);
fopc->client = client;
fopc->operation_id = GNUNET_ntohll (msg->operation_id);
}
+/**
+ * Update peer configuration
+ *
+ * @param peer the peer to update
+ * @param cfg the new configuration
+ * @return error message (freshly allocated); NULL upon success
+ */
+static char *
+update_peer_config (struct Peer *peer,
+ struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ char *emsg;
+
+ GNUNET_TESTING_peer_destroy (peer->details.local.peer);
+ GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
+ peer->details.local.cfg = cfg;
+ emsg = NULL;
+ peer->details.local.peer
+ = GNUNET_TESTING_peer_configure (GST_context->system,
+ peer->details.local.cfg, peer->id,
+ NULL /* Peer id */ ,
+ &emsg);
+ return emsg;
+}
+
+
/**
* Callback to inform whether the peer is running or stopped.
*
struct PeerReconfigureContext *prc = cls;
struct Peer *peer;
char *emsg;
-
+
GNUNET_assert (VALID_PEER_ID (prc->peer_id));
peer = GST_peer_list [prc->peer_id];
GNUNET_assert (GNUNET_NO == peer->is_remote);
- GNUNET_TESTING_peer_destroy (peer->details.local.peer);
- GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
- peer->details.local.cfg = prc->cfg;
+ emsg = update_peer_config (peer, prc->cfg);
prc->cfg = NULL;
prc->stopped = 1;
- emsg = NULL;
- peer->details.local.peer
- = GNUNET_TESTING_peer_configure (GST_context->system,
- peer->details.local.cfg, peer->id,
- NULL /* Peer id */ ,
- &emsg);
- if (NULL == peer->details.local.peer)
+ if (NULL != emsg)
{
GST_send_operation_fail_msg (prc->client, prc->op_id, emsg);
goto cleanup;
}
if (GNUNET_OK != start_peer (peer))
{
-
GST_send_operation_fail_msg (prc->client, prc->op_id,
"Failed to start reconfigured peer");
goto cleanup;
}
GST_send_operation_success_msg (prc->client, prc->op_id);
-
+
cleanup:
cleanup_prc (prc);
return;
struct GNUNET_CONFIGURATION_Handle *cfg;
struct ForwardedOperationContext *fopc;
struct PeerReconfigureContext *prc;
+ char *emsg;
uint64_t op_id;
uint32_t peer_id;
uint16_t msize;
-
+
msize = ntohs (message->size);
if (msize <= sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage))
{
if (GNUNET_YES == peer->is_remote)
{
LOG_DEBUG ("Forwarding PEER_RECONFIGURE for peer: %u\n", peer_id);
- fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
+ fopc = GNUNET_new (struct ForwardedOperationContext);
GNUNET_SERVER_client_keep (client);
fopc->client = client;
fopc->operation_id = op_id;
cfg = GNUNET_TESTBED_extract_config_ (message);
if (NULL == cfg)
{
- GNUNET_break (0);
+ GNUNET_break (0);
GST_send_operation_fail_msg (client, op_id, "Compression error");
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
- prc = GNUNET_malloc (sizeof (struct PeerReconfigureContext));
+ if (GNUNET_NO == peer->details.local.is_running)
+ {
+ emsg = update_peer_config (peer, cfg);
+ if (NULL != emsg)
+ GST_send_operation_fail_msg (client, op_id, emsg);
+ GST_send_operation_success_msg (client, op_id);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ GNUNET_free_non_null (emsg);
+ return;
+ }
+ prc = GNUNET_new (struct PeerReconfigureContext);
+ if (GNUNET_OK !=
+ GNUNET_TESTING_peer_stop_async (peer->details.local.peer, &prc_stop_cb,
+ prc))
+ {
+ GNUNET_assert (0 < GNUNET_asprintf (&emsg,
+ "Error trying to stop peer %u asynchronously\n",
+ peer_id));
+ LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
+ GST_send_operation_fail_msg (client, op_id, emsg);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ GNUNET_free (prc);
+ GNUNET_free (emsg);
+ return;
+ }
prc->cfg = cfg;
prc->peer_id = peer_id;
prc->op_id = op_id;
- prc->client = client;
+ prc->client = client;
GNUNET_SERVER_client_keep (client);
GNUNET_CONTAINER_DLL_insert_tail (prc_head, prc_tail, prc);
- GNUNET_TESTING_peer_stop_async (peer->details.local.peer, prc_stop_cb, prc);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
* @param result result of the operation
*/
static void
-service_manage_result_cb (void *cls,
- enum GNUNET_ARM_RequestStatus rs,
+service_manage_result_cb (void *cls,
+ enum GNUNET_ARM_RequestStatus rs,
const char *service, enum GNUNET_ARM_Result result)
{
struct ManageServiceContext *mctx = cls;
goto ret;
}
/* service started successfully */
-
+
ret:
if (NULL != emsg)
{
uint64_t op_id;
uint32_t peer_id;
uint16_t msize;
-
+
msize = ntohs (message->size);
if (msize <= sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage))
{
- GNUNET_break_op (0);
+ GNUNET_break_op (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
msg = (const struct GNUNET_TESTBED_ManagePeerServiceMessage *) message;
- service = (const char *) &msg[1];
+ service = (const char *) &msg[1];
if ('\0' != service[msize - sizeof
(struct GNUNET_TESTBED_ManagePeerServiceMessage) - 1])
{
{
GNUNET_break_op (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
+ return;
}
peer_id = ntohl (msg->peer_id);
op_id = GNUNET_ntohll (msg->operation_id);
if (GNUNET_YES == peer->is_remote)
{
/* Forward the destory message to sub controller */
- fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
+ fopc = GNUNET_new (struct ForwardedOperationContext);
GNUNET_SERVER_client_keep (client);
fopc->client = client;
fopc->cls = peer;
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
+ if (GNUNET_NO == peer->details.local.is_running)
+ {
+ emsg = GNUNET_strdup ("Peer not running\n");
+ goto err_ret;
+ }
if ((0 != peer->reference_cnt)
&& ( (0 == strcasecmp ("core", service))
|| (0 == strcasecmp ("transport", service)) ) )
peer_id);
goto err_ret;
}
- mctx = GNUNET_malloc (sizeof (struct ManageServiceContext));
+ mctx = GNUNET_new (struct ManageServiceContext);
mctx->peer = peer;
peer->reference_cnt++;
mctx->op_id = op_id;
{
peer = GST_peer_list[id];
if (NULL == peer)
- continue;
+ continue;
if (GNUNET_NO == peer->is_remote)
{
if (GNUNET_YES == peer->details.local.is_running)
}
-/**
- * Task run upon timeout of forwarded SHUTDOWN_PEERS operation
- *
- * @param cls the ForwardedOperationContext
- * @param tc the scheduler task context
- */
-static void
-shutdown_peers_timeout_cb (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct ForwardedOperationContext *fo_ctxt = cls;
- struct HandlerContext_ShutdownPeers *hc;
-
- fo_ctxt->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- hc = fo_ctxt->cls;
- hc->timeout = GNUNET_YES;
- GNUNET_assert (0 < hc->nslaves);
- hc->nslaves--;
- if (0 == hc->nslaves)
- {
- GST_send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id,
- "Timeout at a slave controller");
- GNUNET_free (hc);
- hc = NULL;
- }
- GNUNET_TESTBED_forward_operation_msg_cancel_ (fo_ctxt->opc);
- GNUNET_SERVER_client_drop (fo_ctxt->client);
- GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt);
- GNUNET_free (fo_ctxt);
-}
-
-
/**
* The reply msg handler forwarded SHUTDOWN_PEERS operation. Checks if a
* success reply is received from all clients and then sends the success message
{
struct ForwardedOperationContext *fo_ctxt = cls;
struct HandlerContext_ShutdownPeers *hc;
-
+
hc = fo_ctxt->cls;
- GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != fo_ctxt->timeout_task);
- GNUNET_SCHEDULER_cancel (fo_ctxt->timeout_task);
- fo_ctxt->timeout_task = GNUNET_SCHEDULER_NO_TASK;
GNUNET_assert (0 < hc->nslaves);
hc->nslaves--;
- if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS !=
+ if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS !=
ntohs (msg->type))
hc->timeout = GNUNET_YES;
if (0 == hc->nslaves)
GST_clear_fopcq ();
/* Forward to all slaves which we have started */
op_id = GNUNET_ntohll (msg->operation_id);
- hc = GNUNET_malloc (sizeof (struct HandlerContext_ShutdownPeers));
+ hc = GNUNET_new (struct HandlerContext_ShutdownPeers);
/* FIXME: have a better implementation where we track which slaves are
started by this controller */
for (cnt = 0; cnt < GST_slave_list_size; cnt++)
continue;
LOG_DEBUG ("Forwarding SHUTDOWN_PEERS\n");
hc->nslaves++;
- fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
+ fo_ctxt = GNUNET_new (struct ForwardedOperationContext);
GNUNET_SERVER_client_keep (client);
fo_ctxt->client = client;
fo_ctxt->operation_id = op_id;
&msg->header,
shutdown_peers_reply_cb,
fo_ctxt);
- fo_ctxt->timeout_task =
- GNUNET_SCHEDULER_add_delayed (GST_timeout, &shutdown_peers_timeout_cb,
- fo_ctxt);
GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt);
}
LOG_DEBUG ("Shutting down peers\n");
GST_send_operation_success_msg (client, op_id);
GNUNET_free (hc);
}
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
}