summaryrefslogtreecommitdiff
path: root/src/arm/gnunet-service-arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arm/gnunet-service-arm.c')
-rw-r--r--src/arm/gnunet-service-arm.c101
1 files changed, 81 insertions, 20 deletions
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c
index e02314b91..b30ae518e 100644
--- a/src/arm/gnunet-service-arm.c
+++ b/src/arm/gnunet-service-arm.c
@@ -164,6 +164,11 @@ struct ServiceList {
164 struct GNUNET_TIME_Relative backoff; 164 struct GNUNET_TIME_Relative backoff;
165 165
166 /** 166 /**
167 * Absolute time at which the process was (re-)started last.
168 */
169 struct GNUNET_TIME_Absolute last_started_at;
170
171 /**
167 * Absolute time at which the process is scheduled to restart in case of death 172 * Absolute time at which the process is scheduled to restart in case of death
168 */ 173 */
169 struct GNUNET_TIME_Absolute restart_at; 174 struct GNUNET_TIME_Absolute restart_at;
@@ -186,6 +191,11 @@ struct ServiceList {
186 * are on Windoze). 191 * are on Windoze).
187 */ 192 */
188 int pipe_control; 193 int pipe_control;
194
195 /**
196 * Last exit status of the process.
197 */
198 int last_exit_status;
189}; 199};
190 200
191/** 201/**
@@ -696,7 +706,7 @@ signal_result(struct GNUNET_SERVICE_Client *client,
696 */ 706 */
697static void 707static void
698broadcast_status(const char *name, 708broadcast_status(const char *name,
699 enum GNUNET_ARM_ServiceStatus status, 709 enum GNUNET_ARM_ServiceMonitorStatus status,
700 struct GNUNET_SERVICE_Client *unicast) 710 struct GNUNET_SERVICE_Client *unicast)
701{ 711{
702 struct GNUNET_MQ_Envelope *env; 712 struct GNUNET_MQ_Envelope *env;
@@ -914,6 +924,7 @@ start_process(struct ServiceList *sl,
914 } 924 }
915 GNUNET_free(binary); 925 GNUNET_free(binary);
916 GNUNET_free(quotedbinary); 926 GNUNET_free(quotedbinary);
927 sl->last_started_at = GNUNET_TIME_absolute_get ();
917 if (NULL == sl->proc) 928 if (NULL == sl->proc)
918 { 929 {
919 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, 930 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
@@ -1300,6 +1311,29 @@ handle_stop(void *cls, const struct GNUNET_ARM_Message *amsg)
1300 1311
1301 1312
1302/** 1313/**
1314 * Write a string to a string pool.
1315 *
1316 * @param pool_start pointer to the start of the string pool
1317 * @param pool_size size of the string pool
1318 * @param[in,out] pool_pos current position index in the string pool,
1319 * will be updated
1320 * @param str string to write to the string pool
1321 * @returns GNUNET_OK if the string fits into the pool,
1322 * GNUNET_SYSERR otherwise
1323 */
1324static int
1325pool_write(char *pool_start, size_t pool_size, size_t *pool_pos, char *str)
1326{
1327 size_t next_pos = (*pool_pos) + strlen (str) + 1;
1328
1329 if (next_pos > pool_size)
1330 return GNUNET_SYSERR;
1331 memcpy (pool_start + *pool_pos, str, strlen (str) + 1);
1332 *pool_pos = next_pos;
1333 return GNUNET_OK;
1334}
1335
1336/**
1303 * Handle LIST-message. 1337 * Handle LIST-message.
1304 * 1338 *
1305 * @param cls identification of the client 1339 * @param cls identification of the client
@@ -1311,42 +1345,68 @@ handle_list(void *cls, const struct GNUNET_ARM_Message *request)
1311 struct GNUNET_SERVICE_Client *client = cls; 1345 struct GNUNET_SERVICE_Client *client = cls;
1312 struct GNUNET_MQ_Envelope *env; 1346 struct GNUNET_MQ_Envelope *env;
1313 struct GNUNET_ARM_ListResultMessage *msg; 1347 struct GNUNET_ARM_ListResultMessage *msg;
1314 size_t string_list_size; 1348 size_t extra_size;
1315 struct ServiceList *sl; 1349 struct ServiceList *sl;
1316 uint16_t count; 1350 uint16_t count;
1317 char *pos; 1351 size_t pool_size;
1352 size_t pool_pos;
1353 char *pool_start;
1354 struct GNUNET_ARM_ServiceInfoMessage *ssm;
1318 1355
1319 GNUNET_break(0 == ntohl(request->reserved)); 1356 GNUNET_break_op(0 == ntohl(request->reserved));
1320 count = 0; 1357 count = 0;
1321 string_list_size = 0; 1358 pool_size = 0;
1322 1359
1323 /* first count the running processes get their name's size */ 1360 /* Do one pass over the list to compute the number of services
1361 * and the string pool size */
1324 for (sl = running_head; NULL != sl; sl = sl->next) 1362 for (sl = running_head; NULL != sl; sl = sl->next)
1325 { 1363 {
1326 if (NULL != sl->proc) 1364 pool_size += strlen(sl->name) + 1;
1327 { 1365 pool_size += strlen(sl->binary) + 1;
1328 string_list_size += strlen(sl->name); 1366 count++;
1329 string_list_size += strlen(sl->binary);
1330 string_list_size += 4;
1331 count++;
1332 }
1333 } 1367 }
1334 1368
1369 extra_size = pool_size + (count * sizeof (struct GNUNET_ARM_ServiceInfoMessage));
1335 env = GNUNET_MQ_msg_extra(msg, 1370 env = GNUNET_MQ_msg_extra(msg,
1336 string_list_size, 1371 extra_size,
1337 GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT); 1372 GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT);
1338 msg->arm_msg.request_id = request->request_id; 1373 msg->arm_msg.request_id = request->request_id;
1339 msg->count = htons(count); 1374 msg->count = htons(count);
1340 1375
1341 pos = (char *)&msg[1]; 1376 ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &msg[1];
1377 pool_start = (char *) (ssm + count);
1378 pool_pos = 0;
1379
1342 for (sl = running_head; NULL != sl; sl = sl->next) 1380 for (sl = running_head; NULL != sl; sl = sl->next)
1343 { 1381 {
1344 if (NULL != sl->proc) 1382 ssm->name_index = htons ((uint16_t) pool_pos);
1383 GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos, sl->name));
1384 ssm->binary_index = htons ((uint16_t) pool_pos);
1385 GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos, sl->binary));
1386 if (NULL == sl->proc)
1387 {
1388 if (0 == sl->last_started_at.abs_value_us)
1389 {
1390 /* Process never started */
1391 ssm->status = htonl (GNUNET_ARM_SERVICE_STATUS_STOPPED);
1392 }
1393 else if (0 == sl->last_exit_status)
1345 { 1394 {
1346 size_t s = strlen(sl->name) + strlen(sl->binary) + 4; 1395 ssm->status = htonl (GNUNET_ARM_SERVICE_STATUS_FINISHED);
1347 GNUNET_snprintf(pos, s, "%s (%s)", sl->name, sl->binary);
1348 pos += s;
1349 } 1396 }
1397 else
1398 {
1399 ssm->status = htonl (GNUNET_ARM_SERVICE_STATUS_FAILED);
1400 ssm->last_exit_status = htons (sl->last_exit_status);
1401 }
1402 }
1403 else
1404 {
1405 ssm->status = htonl (GNUNET_ARM_SERVICE_STATUS_STARTED);
1406 }
1407 ssm->last_started_at = GNUNET_TIME_absolute_hton (sl->last_started_at);
1408 ssm->restart_at = GNUNET_TIME_absolute_hton (sl->restart_at);
1409 ssm++;
1350 } 1410 }
1351 GNUNET_MQ_send(GNUNET_SERVICE_client_get_mq(client), env); 1411 GNUNET_MQ_send(GNUNET_SERVICE_client_get_mq(client), env);
1352 GNUNET_SERVICE_client_continue(client); 1412 GNUNET_SERVICE_client_continue(client);
@@ -1700,6 +1760,7 @@ maint_child_death(void *cls)
1700 } 1760 }
1701 if (GNUNET_YES != in_shutdown) 1761 if (GNUNET_YES != in_shutdown)
1702 { 1762 {
1763 pos->last_exit_status = statcode;
1703 if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0)) 1764 if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0))
1704 { 1765 {
1705 /* process terminated normally, allow restart at any time */ 1766 /* process terminated normally, allow restart at any time */
@@ -1722,7 +1783,7 @@ maint_child_death(void *cls)
1722 else 1783 else
1723 { 1784 {
1724 GNUNET_log( 1785 GNUNET_log(
1725 GNUNET_ERROR_TYPE_INFO, 1786 GNUNET_ERROR_TYPE_WARNING,
1726 _("Service `%s' terminated with status %s/%d, will restart in %s\n"), 1787 _("Service `%s' terminated with status %s/%d, will restart in %s\n"),
1727 pos->name, 1788 pos->name,
1728 statstr, 1789 statstr,