diff options
author | Florian Dold <florian.dold@gmail.com> | 2019-09-24 17:59:18 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2019-09-24 17:59:18 +0200 |
commit | 6aa35f62a80056f31ccd97133a0764a0950e1566 (patch) | |
tree | 1a42157c50d6cd3d3332e6b4554a94222bc6adb9 | |
parent | 2e2790e1b4a563ef471be1b604c6ebee55f89203 (diff) | |
download | gnunet-6aa35f62a80056f31ccd97133a0764a0950e1566.tar.gz gnunet-6aa35f62a80056f31ccd97133a0764a0950e1566.zip |
implement extended status information for arm
-rw-r--r-- | src/arm/arm.h | 45 | ||||
-rw-r--r-- | src/arm/arm_api.c | 102 | ||||
-rw-r--r-- | src/arm/arm_monitor_api.c | 8 | ||||
-rw-r--r-- | src/arm/gnunet-arm.c | 51 | ||||
-rw-r--r-- | src/arm/gnunet-service-arm.c | 101 | ||||
-rw-r--r-- | src/arm/test_exponential_backoff.c | 2 | ||||
-rw-r--r-- | src/arm/test_gnunet_service_arm.c | 10 | ||||
-rw-r--r-- | src/include/gnunet_arm_service.h | 78 |
8 files changed, 331 insertions, 66 deletions
diff --git a/src/arm/arm.h b/src/arm/arm.h index 983586060..bddcd7cf3 100644 --- a/src/arm/arm.h +++ b/src/arm/arm.h | |||
@@ -93,6 +93,44 @@ struct GNUNET_ARM_ResultMessage { | |||
93 | uint32_t result; | 93 | uint32_t result; |
94 | }; | 94 | }; |
95 | 95 | ||
96 | struct GNUNET_ARM_ServiceInfoMessage { | ||
97 | /** | ||
98 | * String pool index for the service's name. | ||
99 | */ | ||
100 | uint16_t name_index; | ||
101 | |||
102 | /** | ||
103 | * String pool index for the service's binary. | ||
104 | */ | ||
105 | uint16_t binary_index; | ||
106 | |||
107 | /** | ||
108 | * Last process exit status. | ||
109 | */ | ||
110 | int16_t last_exit_status; | ||
111 | |||
112 | /** | ||
113 | * Padding. | ||
114 | */ | ||
115 | uint16_t padding; | ||
116 | |||
117 | /** | ||
118 | * Status from the 'enum GNUNET_ARM_ServiceStatus' | ||
119 | */ | ||
120 | uint32_t status; | ||
121 | |||
122 | /** | ||
123 | * Time when the sevice will be restarted, if applicable | ||
124 | * to the current status. | ||
125 | */ | ||
126 | struct GNUNET_TIME_AbsoluteNBO restart_at; | ||
127 | |||
128 | /** | ||
129 | * Time when the sevice was first started, if applicable. | ||
130 | */ | ||
131 | struct GNUNET_TIME_AbsoluteNBO last_started_at; | ||
132 | }; | ||
133 | |||
96 | /** | 134 | /** |
97 | * Reply from ARM to client for the | 135 | * Reply from ARM to client for the |
98 | * #GNUNET_MESSAGE_TYPE_ARM_LIST request followed by count | 136 | * #GNUNET_MESSAGE_TYPE_ARM_LIST request followed by count |
@@ -107,10 +145,13 @@ struct GNUNET_ARM_ListResultMessage { | |||
107 | struct GNUNET_ARM_Message arm_msg; | 145 | struct GNUNET_ARM_Message arm_msg; |
108 | 146 | ||
109 | /** | 147 | /** |
110 | * Number of '\0' terminated strings that follow | 148 | * Number of 'struct GNUNET_ARM_ServiceInfoMessage' that |
111 | * this message. | 149 | * are at the end of this message. |
112 | */ | 150 | */ |
113 | uint16_t count; | 151 | uint16_t count; |
152 | |||
153 | /* struct GNUNET_ARM_ServiceInfoMessage[count]; */ | ||
154 | /* pool of 0-terminated strings */ | ||
114 | }; | 155 | }; |
115 | 156 | ||
116 | GNUNET_NETWORK_STRUCT_END | 157 | GNUNET_NETWORK_STRUCT_END |
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c index b42c95dc0..4c3bb0488 100644 --- a/src/arm/arm_api.c +++ b/src/arm/arm_api.c | |||
@@ -294,7 +294,32 @@ handle_arm_result(void *cls, const struct GNUNET_ARM_ResultMessage *res) | |||
294 | 294 | ||
295 | 295 | ||
296 | /** | 296 | /** |
297 | * Checked that list result message is well-formed. | 297 | * Read from a string pool. |
298 | * | ||
299 | * @param pool_start start of the string pool | ||
300 | * @param pool_size size of the string pool | ||
301 | * @param str_index index into the string pool | ||
302 | * @returns an index into the string pool, or | ||
303 | * NULL if the index is out of bounds | ||
304 | */ | ||
305 | static const char * | ||
306 | pool_get (const char *pool_start, size_t pool_size, size_t str_index) | ||
307 | { | ||
308 | const char *str_start; | ||
309 | const char *end; | ||
310 | |||
311 | if (str_index >= pool_size) | ||
312 | return NULL; | ||
313 | str_start = pool_start + str_index; | ||
314 | end = memchr(str_start, 0, pool_size - str_index); | ||
315 | if (NULL == end) | ||
316 | return NULL; | ||
317 | return str_start; | ||
318 | } | ||
319 | |||
320 | |||
321 | /** | ||
322 | * Check that list result message is well-formed. | ||
298 | * | 323 | * |
299 | * @param cls our `struct GNUNET_ARM_Handle` | 324 | * @param cls our `struct GNUNET_ARM_Handle` |
300 | * @param lres the message received from the arm service | 325 | * @param lres the message received from the arm service |
@@ -304,23 +329,38 @@ static int | |||
304 | check_arm_list_result(void *cls, | 329 | check_arm_list_result(void *cls, |
305 | const struct GNUNET_ARM_ListResultMessage *lres) | 330 | const struct GNUNET_ARM_ListResultMessage *lres) |
306 | { | 331 | { |
307 | const char *pos = (const char *)&lres[1]; | ||
308 | uint16_t rcount = ntohs(lres->count); | 332 | uint16_t rcount = ntohs(lres->count); |
309 | uint16_t msize = ntohs(lres->arm_msg.header.size) - sizeof(*lres); | 333 | uint16_t msize = ntohs(lres->arm_msg.header.size) - sizeof(*lres); |
310 | uint16_t size_check; | 334 | struct GNUNET_ARM_ServiceInfoMessage *ssm; |
335 | size_t pool_size; | ||
336 | char *pool_start; | ||
337 | |||
338 | if ((rcount * sizeof (struct GNUNET_ARM_ServiceInfoMessage) > msize)) | ||
339 | { | ||
340 | GNUNET_break_op (0); | ||
341 | return GNUNET_NO; | ||
342 | } | ||
343 | |||
344 | ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &lres[1]; | ||
345 | pool_start = (char *) (ssm + rcount); | ||
346 | pool_size = msize - (rcount * sizeof (struct GNUNET_ARM_ServiceInfoMessage)); | ||
311 | 347 | ||
312 | (void)cls; | 348 | (void)cls; |
313 | size_check = 0; | ||
314 | for (unsigned int i = 0; i < rcount; i++) | 349 | for (unsigned int i = 0; i < rcount; i++) |
315 | { | 350 | { |
316 | const char *end = memchr(pos, 0, msize - size_check); | 351 | uint16_t name_index = ntohs (ssm->name_index); |
317 | if (NULL == end) | 352 | uint16_t binary_index = ntohs (ssm->binary_index); |
318 | { | 353 | if (NULL == pool_get (pool_start, pool_size, name_index)) |
319 | GNUNET_break(0); | 354 | { |
320 | return GNUNET_SYSERR; | 355 | GNUNET_break_op (0); |
321 | } | 356 | return GNUNET_NO; |
322 | size_check += (end - pos) + 1; | 357 | } |
323 | pos = end + 1; | 358 | if (NULL == pool_get (pool_start, pool_size, binary_index)) |
359 | { | ||
360 | GNUNET_break_op (0); | ||
361 | return GNUNET_NO; | ||
362 | } | ||
363 | ssm++; | ||
324 | } | 364 | } |
325 | return GNUNET_OK; | 365 | return GNUNET_OK; |
326 | } | 366 | } |
@@ -338,12 +378,13 @@ handle_arm_list_result(void *cls, | |||
338 | { | 378 | { |
339 | struct GNUNET_ARM_Handle *h = cls; | 379 | struct GNUNET_ARM_Handle *h = cls; |
340 | uint16_t rcount = ntohs(lres->count); | 380 | uint16_t rcount = ntohs(lres->count); |
341 | const char *list[rcount]; | ||
342 | const char *pos = (const char *)&lres[1]; | ||
343 | uint16_t msize = ntohs(lres->arm_msg.header.size) - sizeof(*lres); | 381 | uint16_t msize = ntohs(lres->arm_msg.header.size) - sizeof(*lres); |
382 | struct GNUNET_ARM_ServiceInfo list[rcount]; | ||
383 | struct GNUNET_ARM_ServiceInfoMessage *ssm; | ||
344 | struct GNUNET_ARM_Operation *op; | 384 | struct GNUNET_ARM_Operation *op; |
345 | uint16_t size_check; | ||
346 | uint64_t id; | 385 | uint64_t id; |
386 | size_t pool_size; | ||
387 | char *pool_start; | ||
347 | 388 | ||
348 | id = GNUNET_ntohll(lres->arm_msg.request_id); | 389 | id = GNUNET_ntohll(lres->arm_msg.request_id); |
349 | op = find_op_by_id(h, id); | 390 | op = find_op_by_id(h, id); |
@@ -354,16 +395,31 @@ handle_arm_list_result(void *cls, | |||
354 | (unsigned long long)id); | 395 | (unsigned long long)id); |
355 | return; | 396 | return; |
356 | } | 397 | } |
357 | size_check = 0; | 398 | |
399 | GNUNET_assert ((rcount * sizeof (struct GNUNET_ARM_ServiceInfoMessage) <= msize)); | ||
400 | |||
401 | ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &lres[1]; | ||
402 | pool_start = (char *) (ssm + rcount); | ||
403 | pool_size = msize - (rcount * sizeof (struct GNUNET_ARM_ServiceInfoMessage)); | ||
404 | |||
358 | for (unsigned int i = 0; i < rcount; i++) | 405 | for (unsigned int i = 0; i < rcount; i++) |
359 | { | 406 | { |
360 | const char *end = memchr(pos, 0, msize - size_check); | 407 | uint16_t name_index = ntohs (ssm->name_index); |
361 | 408 | uint16_t binary_index = ntohs (ssm->binary_index); | |
362 | /* Assert, as this was already checked in #check_arm_list_result() */ | 409 | const char *name; |
363 | GNUNET_assert(NULL != end); | 410 | const char *binary; |
364 | list[i] = pos; | 411 | |
365 | size_check += (end - pos) + 1; | 412 | GNUNET_assert (NULL != (name = pool_get (pool_start, pool_size, name_index))); |
366 | pos = end + 1; | 413 | GNUNET_assert (NULL != (binary = pool_get (pool_start, pool_size, binary_index))); |
414 | list[i] = (struct GNUNET_ARM_ServiceInfo) { | ||
415 | .name = name, | ||
416 | .binary = binary, | ||
417 | .status = ntohl (ssm->status), | ||
418 | .last_started_at = GNUNET_TIME_absolute_ntoh (ssm->last_started_at), | ||
419 | .restart_at = GNUNET_TIME_absolute_ntoh (ssm->restart_at), | ||
420 | .last_exit_status = ntohs (ssm->last_exit_status), | ||
421 | }; | ||
422 | ssm++; | ||
367 | } | 423 | } |
368 | if (NULL != op->list_cont) | 424 | if (NULL != op->list_cont) |
369 | op->list_cont(op->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, rcount, list); | 425 | op->list_cont(op->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, rcount, list); |
diff --git a/src/arm/arm_monitor_api.c b/src/arm/arm_monitor_api.c index c6e1e2683..00faaaef1 100644 --- a/src/arm/arm_monitor_api.c +++ b/src/arm/arm_monitor_api.c | |||
@@ -61,7 +61,7 @@ struct GNUNET_ARM_MonitorHandle { | |||
61 | /** | 61 | /** |
62 | * Callback to invoke on status updates. | 62 | * Callback to invoke on status updates. |
63 | */ | 63 | */ |
64 | GNUNET_ARM_ServiceStatusCallback service_status; | 64 | GNUNET_ARM_ServiceMonitorCallback service_status; |
65 | 65 | ||
66 | /** | 66 | /** |
67 | * Closure for @e service_status. | 67 | * Closure for @e service_status. |
@@ -153,9 +153,9 @@ static void | |||
153 | handle_monitor_notify(void *cls, const struct GNUNET_ARM_StatusMessage *res) | 153 | handle_monitor_notify(void *cls, const struct GNUNET_ARM_StatusMessage *res) |
154 | { | 154 | { |
155 | struct GNUNET_ARM_MonitorHandle *h = cls; | 155 | struct GNUNET_ARM_MonitorHandle *h = cls; |
156 | enum GNUNET_ARM_ServiceStatus status; | 156 | enum GNUNET_ARM_ServiceMonitorStatus status; |
157 | 157 | ||
158 | status = (enum GNUNET_ARM_ServiceStatus)ntohl(res->status); | 158 | status = (enum GNUNET_ARM_ServiceMonitorStatus)ntohl(res->status); |
159 | LOG(GNUNET_ERROR_TYPE_DEBUG, | 159 | LOG(GNUNET_ERROR_TYPE_DEBUG, |
160 | "Received notification from ARM for service `%s' with status %d\n", | 160 | "Received notification from ARM for service `%s' with status %d\n", |
161 | (const char *)&res[1], | 161 | (const char *)&res[1], |
@@ -230,7 +230,7 @@ reconnect_arm_monitor(struct GNUNET_ARM_MonitorHandle *h) | |||
230 | */ | 230 | */ |
231 | struct GNUNET_ARM_MonitorHandle * | 231 | struct GNUNET_ARM_MonitorHandle * |
232 | GNUNET_ARM_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, | 232 | GNUNET_ARM_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, |
233 | GNUNET_ARM_ServiceStatusCallback cont, | 233 | GNUNET_ARM_ServiceMonitorCallback cont, |
234 | void *cont_cls) | 234 | void *cont_cls) |
235 | { | 235 | { |
236 | struct GNUNET_ARM_MonitorHandle *h; | 236 | struct GNUNET_ARM_MonitorHandle *h; |
diff --git a/src/arm/gnunet-arm.c b/src/arm/gnunet-arm.c index 3396a4dbe..fcbff2331 100644 --- a/src/arm/gnunet-arm.c +++ b/src/arm/gnunet-arm.c | |||
@@ -54,6 +54,11 @@ static int delete; | |||
54 | static int quiet; | 54 | static int quiet; |
55 | 55 | ||
56 | /** | 56 | /** |
57 | * Set if we should print all services, including stopped ones. | ||
58 | */ | ||
59 | static int show_all; | ||
60 | |||
61 | /** | ||
57 | * Monitor ARM activity. | 62 | * Monitor ARM activity. |
58 | */ | 63 | */ |
59 | static int monitor; | 64 | static int monitor; |
@@ -508,13 +513,13 @@ term_callback(void *cls, | |||
508 | * @param cls closure (unused) | 513 | * @param cls closure (unused) |
509 | * @param rs request status (success, failure, etc.) | 514 | * @param rs request status (success, failure, etc.) |
510 | * @param count number of services in the list | 515 | * @param count number of services in the list |
511 | * @param list list of services that are running | 516 | * @param list list of services managed by arm |
512 | */ | 517 | */ |
513 | static void | 518 | static void |
514 | list_callback(void *cls, | 519 | list_callback(void *cls, |
515 | enum GNUNET_ARM_RequestStatus rs, | 520 | enum GNUNET_ARM_RequestStatus rs, |
516 | unsigned int count, | 521 | unsigned int count, |
517 | const char *const *list) | 522 | const struct GNUNET_ARM_ServiceInfo *list) |
518 | { | 523 | { |
519 | (void)cls; | 524 | (void)cls; |
520 | op = NULL; | 525 | op = NULL; |
@@ -540,9 +545,41 @@ list_callback(void *cls, | |||
540 | return; | 545 | return; |
541 | } | 546 | } |
542 | if (!quiet) | 547 | if (!quiet) |
543 | fprintf(stdout, "%s", _("Running services:\n")); | 548 | { |
549 | if (show_all) | ||
550 | fprintf(stdout, "%s", _("All services:\n")); | ||
551 | else | ||
552 | fprintf(stdout, "%s", _("Services (excluding stopped services):\n")); | ||
553 | } | ||
544 | for (unsigned int i = 0; i < count; i++) | 554 | for (unsigned int i = 0; i < count; i++) |
545 | fprintf(stdout, "%s\n", list[i]); | 555 | { |
556 | struct GNUNET_TIME_Relative restart_in; | ||
557 | switch (list[i].status) | ||
558 | { | ||
559 | case GNUNET_ARM_SERVICE_STATUS_STOPPED: | ||
560 | if (show_all) | ||
561 | fprintf(stdout, "%s (binary='%s', status=stopped)\n", list[i].name, list[i].binary); | ||
562 | break; | ||
563 | case GNUNET_ARM_SERVICE_STATUS_FAILED: | ||
564 | restart_in = GNUNET_TIME_absolute_get_remaining (list[i].restart_at); | ||
565 | fprintf(stdout, "%s (binary='%s', status=failed, exit_status=%d, restart_delay='%s')\n", | ||
566 | list[i].name, | ||
567 | list[i].binary, | ||
568 | list[i].last_exit_status, | ||
569 | GNUNET_STRINGS_relative_time_to_string (restart_in, GNUNET_YES)); | ||
570 | break; | ||
571 | case GNUNET_ARM_SERVICE_STATUS_FINISHED: | ||
572 | fprintf(stdout, "%s (binary='%s', status=finished)\n", list[i].name, list[i].binary); | ||
573 | break; | ||
574 | case GNUNET_ARM_SERVICE_STATUS_STARTED: | ||
575 | fprintf(stdout, "%s (binary='%s', status=started)\n", list[i].name, list[i].binary); | ||
576 | break; | ||
577 | default: | ||
578 | fprintf(stdout, "%s (binary='%s', status=unknown)\n", list[i].name, list[i].binary); | ||
579 | break; | ||
580 | |||
581 | } | ||
582 | } | ||
546 | al_task = GNUNET_SCHEDULER_add_now(&action_loop, NULL); | 583 | al_task = GNUNET_SCHEDULER_add_now(&action_loop, NULL); |
547 | } | 584 | } |
548 | 585 | ||
@@ -652,7 +689,7 @@ action_loop(void *cls) | |||
652 | static void | 689 | static void |
653 | srv_status(void *cls, | 690 | srv_status(void *cls, |
654 | const char *service, | 691 | const char *service, |
655 | enum GNUNET_ARM_ServiceStatus status) | 692 | enum GNUNET_ARM_ServiceMonitorStatus status) |
656 | { | 693 | { |
657 | const char *msg; | 694 | const char *msg; |
658 | 695 | ||
@@ -773,6 +810,10 @@ main(int argc, char *const *argv) | |||
773 | "SERVICE", | 810 | "SERVICE", |
774 | gettext_noop("stop a particular service"), | 811 | gettext_noop("stop a particular service"), |
775 | &term), | 812 | &term), |
813 | GNUNET_GETOPT_option_flag('a', | ||
814 | "all", | ||
815 | gettext_noop("also show stopped services (used with -I)"), | ||
816 | &show_all), | ||
776 | GNUNET_GETOPT_option_flag('s', | 817 | GNUNET_GETOPT_option_flag('s', |
777 | "start", | 818 | "start", |
778 | gettext_noop( | 819 | gettext_noop( |
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 | */ |
697 | static void | 707 | static void |
698 | broadcast_status(const char *name, | 708 | broadcast_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 | */ | ||
1324 | static int | ||
1325 | pool_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, |
diff --git a/src/arm/test_exponential_backoff.c b/src/arm/test_exponential_backoff.c index 8190d29c2..b13ab1cb8 100644 --- a/src/arm/test_exponential_backoff.c +++ b/src/arm/test_exponential_backoff.c | |||
@@ -196,7 +196,7 @@ arm_stop_cb(void *cls, | |||
196 | static void | 196 | static void |
197 | srv_status(void *cls, | 197 | srv_status(void *cls, |
198 | const char *service, | 198 | const char *service, |
199 | enum GNUNET_ARM_ServiceStatus status) | 199 | enum GNUNET_ARM_ServiceMonitorStatus status) |
200 | { | 200 | { |
201 | if (status == GNUNET_ARM_SERVICE_MONITORING_STARTED) | 201 | if (status == GNUNET_ARM_SERVICE_MONITORING_STARTED) |
202 | { | 202 | { |
diff --git a/src/arm/test_gnunet_service_arm.c b/src/arm/test_gnunet_service_arm.c index 8c8c664f9..cb2c14438 100644 --- a/src/arm/test_gnunet_service_arm.c +++ b/src/arm/test_gnunet_service_arm.c | |||
@@ -78,7 +78,7 @@ static void | |||
78 | service_list(void *cls, | 78 | service_list(void *cls, |
79 | enum GNUNET_ARM_RequestStatus rs, | 79 | enum GNUNET_ARM_RequestStatus rs, |
80 | unsigned int count, | 80 | unsigned int count, |
81 | const char *const*list) | 81 | const struct GNUNET_ARM_ServiceInfo *list) |
82 | { | 82 | { |
83 | unsigned int i; | 83 | unsigned int i; |
84 | 84 | ||
@@ -89,13 +89,13 @@ service_list(void *cls, | |||
89 | goto stop_arm; | 89 | goto stop_arm; |
90 | for (i = 0; i < count; i++) | 90 | for (i = 0; i < count; i++) |
91 | { | 91 | { |
92 | if (0 == strcasecmp(list[i], | 92 | if ((0 == strcasecmp(list[i].name, "resolver")) && |
93 | "resolver (gnunet-service-resolver)")) | 93 | (0 == strcasecmp(list[i].binary, "gnunet-service-resolver"))) |
94 | { | 94 | { |
95 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | 95 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, |
96 | "Got service list, now stopping arm\n"); | 96 | "Got service list, now stopping arm\n"); |
97 | ret = 0; | 97 | ret = 0; |
98 | } | 98 | } |
99 | } | 99 | } |
100 | 100 | ||
101 | stop_arm: | 101 | stop_arm: |
diff --git a/src/include/gnunet_arm_service.h b/src/include/gnunet_arm_service.h index faf89128f..9e79c26e7 100644 --- a/src/include/gnunet_arm_service.h +++ b/src/include/gnunet_arm_service.h | |||
@@ -70,7 +70,7 @@ enum GNUNET_ARM_RequestStatus { | |||
70 | /** | 70 | /** |
71 | * Statuses of services. | 71 | * Statuses of services. |
72 | */ | 72 | */ |
73 | enum GNUNET_ARM_ServiceStatus { | 73 | enum GNUNET_ARM_ServiceMonitorStatus { |
74 | /** | 74 | /** |
75 | * Dummy message. | 75 | * Dummy message. |
76 | */ | 76 | */ |
@@ -150,6 +150,72 @@ enum GNUNET_ARM_Result { | |||
150 | 150 | ||
151 | 151 | ||
152 | /** | 152 | /** |
153 | * Status of a service managed by ARM. | ||
154 | */ | ||
155 | enum GNUNET_ARM_ServiceStatus | ||
156 | { | ||
157 | /** | ||
158 | * Service is stopped. | ||
159 | */ | ||
160 | GNUNET_ARM_SERVICE_STATUS_STOPPED = 0, | ||
161 | |||
162 | /** | ||
163 | * Service has been started and is currently running. | ||
164 | */ | ||
165 | GNUNET_ARM_SERVICE_STATUS_STARTED = 1, | ||
166 | |||
167 | /** | ||
168 | * The service has previously failed, and | ||
169 | * will be restarted. | ||
170 | */ | ||
171 | GNUNET_ARM_SERVICE_STATUS_FAILED = 2, | ||
172 | |||
173 | /** | ||
174 | * The service was started, but then exited normally. | ||
175 | */ | ||
176 | GNUNET_ARM_SERVICE_STATUS_FINISHED = 3, | ||
177 | }; | ||
178 | |||
179 | |||
180 | /** | ||
181 | * Information about a service managed by ARM. | ||
182 | */ | ||
183 | struct GNUNET_ARM_ServiceInfo | ||
184 | { | ||
185 | /** | ||
186 | * The current status of the service. | ||
187 | */ | ||
188 | enum GNUNET_ARM_ServiceStatus status; | ||
189 | |||
190 | /** | ||
191 | * The name of the service. | ||
192 | */ | ||
193 | const char *name; | ||
194 | |||
195 | /** | ||
196 | * The binary used to execute the service. | ||
197 | */ | ||
198 | const char *binary; | ||
199 | |||
200 | /** | ||
201 | * Time when the sevice will be restarted, if applicable | ||
202 | * to the current status. | ||
203 | */ | ||
204 | struct GNUNET_TIME_Absolute restart_at; | ||
205 | |||
206 | /** | ||
207 | * Time when the sevice was first started, if applicable. | ||
208 | */ | ||
209 | struct GNUNET_TIME_Absolute last_started_at; | ||
210 | |||
211 | /** | ||
212 | * Last process exit status. | ||
213 | */ | ||
214 | int last_exit_status; | ||
215 | }; | ||
216 | |||
217 | |||
218 | /** | ||
153 | * Handle for interacting with ARM. | 219 | * Handle for interacting with ARM. |
154 | */ | 220 | */ |
155 | struct GNUNET_ARM_Handle; | 221 | struct GNUNET_ARM_Handle; |
@@ -197,13 +263,13 @@ typedef void | |||
197 | * @param cls closure | 263 | * @param cls closure |
198 | * @param rs status of the request | 264 | * @param rs status of the request |
199 | * @param count number of strings in the list | 265 | * @param count number of strings in the list |
200 | * @param list list of running services | 266 | * @param list list of services managed by arm |
201 | */ | 267 | */ |
202 | typedef void | 268 | typedef void |
203 | (*GNUNET_ARM_ServiceListCallback) (void *cls, | 269 | (*GNUNET_ARM_ServiceListCallback) (void *cls, |
204 | enum GNUNET_ARM_RequestStatus rs, | 270 | enum GNUNET_ARM_RequestStatus rs, |
205 | unsigned int count, | 271 | unsigned int count, |
206 | const char *const*list); | 272 | const struct GNUNET_ARM_ServiceInfo *list); |
207 | 273 | ||
208 | 274 | ||
209 | /** | 275 | /** |
@@ -309,9 +375,9 @@ struct GNUNET_ARM_MonitorHandle; | |||
309 | * @param status status of the service | 375 | * @param status status of the service |
310 | */ | 376 | */ |
311 | typedef void | 377 | typedef void |
312 | (*GNUNET_ARM_ServiceStatusCallback) (void *cls, | 378 | (*GNUNET_ARM_ServiceMonitorCallback) (void *cls, |
313 | const char *service, | 379 | const char *service, |
314 | enum GNUNET_ARM_ServiceStatus status); | 380 | enum GNUNET_ARM_ServiceMonitorStatus status); |
315 | 381 | ||
316 | 382 | ||
317 | /** | 383 | /** |
@@ -327,7 +393,7 @@ typedef void | |||
327 | */ | 393 | */ |
328 | struct GNUNET_ARM_MonitorHandle * | 394 | struct GNUNET_ARM_MonitorHandle * |
329 | GNUNET_ARM_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, | 395 | GNUNET_ARM_monitor_start(const struct GNUNET_CONFIGURATION_Handle *cfg, |
330 | GNUNET_ARM_ServiceStatusCallback cont, | 396 | GNUNET_ARM_ServiceMonitorCallback cont, |
331 | void *cont_cls); | 397 | void *cont_cls); |
332 | 398 | ||
333 | 399 | ||