This source file includes following definitions.
- orte_show_help_is_available
- tuple_list_item_constructor
- tuple_list_item_destructor
- xml_format
- match
- get_tli
- show_accumulated_duplicates
- show_help
- orte_show_help_recv
- orte_show_help_init
- orte_show_help_finalize
- orte_show_help
- cbfunc
- orte_show_help_norender
- orte_show_help_suppress
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include "orte_config.h"
24 #include "orte/types.h"
25 #include "orte/constants.h"
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <time.h>
30
31 #include "opal/util/show_help.h"
32 #include "opal/util/output.h"
33 #include "opal/util/printf.h"
34 #include "opal/dss/dss.h"
35 #include "opal/mca/event/event.h"
36 #include "opal/mca/pmix/pmix.h"
37
38 #include "orte/mca/errmgr/errmgr.h"
39 #include "orte/mca/rml/rml.h"
40 #include "orte/mca/rml/rml_types.h"
41 #include "orte/mca/routed/routed.h"
42 #include "orte/util/name_fns.h"
43 #include "orte/util/proc_info.h"
44 #include "orte/runtime/orte_globals.h"
45
46 #include "orte/util/show_help.h"
47
48 bool orte_help_want_aggregate = false;
49 static int orte_help_output;
50
51
52
53
54
55 static bool ready = false;
56
57
58
59
60 bool orte_show_help_is_available(void)
61 {
62
63
64
65 return ready;
66 }
67
68
69 typedef struct {
70 opal_list_item_t super;
71
72 char *tli_filename;
73
74 char *tli_topic;
75
76 opal_list_t tli_processes;
77
78 time_t tli_time_displayed;
79
80
81 int tli_count_since_last_display;
82
83 bool tli_display;
84 } tuple_list_item_t;
85
86 static void tuple_list_item_constructor(tuple_list_item_t *obj);
87 static void tuple_list_item_destructor(tuple_list_item_t *obj);
88 static OBJ_CLASS_INSTANCE(tuple_list_item_t, opal_list_item_t,
89 tuple_list_item_constructor,
90 tuple_list_item_destructor);
91
92
93
94 static opal_list_t abd_tuples;
95
96
97 static struct timeval show_help_interval = { 5, 0 };
98
99
100 static time_t show_help_time_last_displayed = 0;
101 static bool show_help_timer_set = false;
102 static opal_event_t show_help_timer_event;
103
104 static opal_show_help_fn_t save_help = NULL;
105
106 static void tuple_list_item_constructor(tuple_list_item_t *obj)
107 {
108 obj->tli_filename = NULL;
109 obj->tli_topic = NULL;
110 OBJ_CONSTRUCT(&(obj->tli_processes), opal_list_t);
111 obj->tli_time_displayed = time(NULL);
112 obj->tli_count_since_last_display = 0;
113 obj->tli_display = true;
114 }
115
116 static void tuple_list_item_destructor(tuple_list_item_t *obj)
117 {
118 opal_list_item_t *item, *next;
119
120 if (NULL != obj->tli_filename) {
121 free(obj->tli_filename);
122 }
123 if (NULL != obj->tli_topic) {
124 free(obj->tli_topic);
125 }
126 for (item = opal_list_get_first(&(obj->tli_processes));
127 opal_list_get_end(&(obj->tli_processes)) != item;
128 item = next) {
129 next = opal_list_get_next(item);
130 opal_list_remove_item(&(obj->tli_processes), item);
131 OBJ_RELEASE(item);
132 }
133 }
134
135
136 static char* xml_format(unsigned char *input)
137 {
138 int i, j, k, len, outlen;
139 char *output, qprint[10];
140 char *endtag="</stderr>";
141 char *starttag="<stderr>";
142 int endtaglen, starttaglen;
143 bool endtagged = false;
144
145 len = strlen((char*)input);
146
147 output = (char*)malloc((len+1024)*sizeof(char));
148 if (NULL == output) {
149 ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
150 return (char*)input;
151 }
152 memset(output, 0, len+1024);
153 outlen = len+1023;
154 endtaglen = strlen(endtag);
155 starttaglen = strlen(starttag);
156
157
158 k=0;
159
160
161 for (j=0; j < starttaglen && k < outlen; j++) {
162 output[k++] = starttag[j];
163 }
164
165 for (i=0; i < len; i++) {
166 if ('&' == input[i]) {
167 if (k+5 >= outlen) {
168 ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
169 goto error;
170 }
171 snprintf(qprint, 10, "&");
172 for (j=0; j < (int)strlen(qprint) && k < outlen; j++) {
173 output[k++] = qprint[j];
174 }
175 } else if ('<' == input[i]) {
176 if (k+4 >= outlen) {
177 ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
178 goto error;
179 }
180 snprintf(qprint, 10, "<");
181 for (j=0; j < (int)strlen(qprint) && k < outlen; j++) {
182 output[k++] = qprint[j];
183 }
184 } else if ('>' == input[i]) {
185 if (k+4 >= outlen) {
186 ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
187 goto error;
188 }
189 snprintf(qprint, 10, ">");
190 for (j=0; j < (int)strlen(qprint) && k < outlen; j++) {
191 output[k++] = qprint[j];
192 }
193 } else if (input[i] < 32 || input[i] > 127) {
194
195 if (k+7 >= outlen) {
196 ORTE_ERROR_LOG(ORTE_ERR_OUT_OF_RESOURCE);
197 goto error;
198 }
199 snprintf(qprint, 10, "&#%03d;", (int)input[i]);
200 for (j=0; j < (int)strlen(qprint) && k < outlen; j++) {
201 output[k++] = qprint[j];
202 }
203
204 if ('\n' == input[i] && (k+endtaglen+1) < outlen) {
205
206 for (j=0; j < endtaglen && k < outlen-1; j++) {
207 output[k++] = endtag[j];
208 }
209
210 output[k++] = '\n';
211
212 if (i < len-1 && (k+starttaglen) < outlen) {
213 for (j=0; j < starttaglen && k < outlen; j++) {
214 output[k++] = starttag[j];
215 endtagged = false;
216 }
217 } else {
218 endtagged = true;
219 }
220 }
221 } else {
222 output[k++] = input[i];
223 }
224 }
225
226 if (!endtagged) {
227
228 for (j=0; j < endtaglen && k < outlen-1; j++) {
229 output[k++] = endtag[j];
230 }
231 output[k++] = '\n';
232 }
233
234 return output;
235
236 error:
237
238
239
240
241 free(output);
242 return (char*)input;
243 }
244
245
246
247
248
249 static int match(const char *a, const char *b)
250 {
251 int rc = ORTE_ERROR;
252 char *p1, *p2, *tmp1 = NULL, *tmp2 = NULL;
253 size_t min;
254
255
256 if (0 == strcmp(a, b)) return ORTE_SUCCESS;
257
258 if (NULL != strchr(a, '*') || NULL != strchr(b, '*')) {
259 tmp1 = strdup(a);
260 if (NULL == tmp1) {
261 return ORTE_ERR_OUT_OF_RESOURCE;
262 }
263 tmp2 = strdup(b);
264 if (NULL == tmp2) {
265 free(tmp1);
266 return ORTE_ERR_OUT_OF_RESOURCE;
267 }
268 p1 = strchr(tmp1, '*');
269 p2 = strchr(tmp2, '*');
270
271 if (NULL != p1) {
272 *p1 = '\0';
273 }
274 if (NULL != p2) {
275 *p2 = '\0';
276 }
277 min = strlen(tmp1);
278 if (strlen(tmp2) < min) {
279 min = strlen(tmp2);
280 }
281 if (0 == min || 0 == strncmp(tmp1, tmp2, min)) {
282 rc = ORTE_SUCCESS;
283 }
284 free(tmp1);
285 free(tmp2);
286 return rc;
287 }
288
289
290 return ORTE_ERROR;
291 }
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307 static int get_tli(const char *filename, const char *topic,
308 tuple_list_item_t **tli)
309 {
310 opal_list_item_t *item;
311
312
313 for (item = opal_list_get_first(&abd_tuples);
314 opal_list_get_end(&abd_tuples) != item;
315 item = opal_list_get_next(item)) {
316 (*tli) = (tuple_list_item_t*) item;
317 if (ORTE_SUCCESS == match((*tli)->tli_filename, filename) &&
318 ORTE_SUCCESS == match((*tli)->tli_topic, topic)) {
319 return ORTE_SUCCESS;
320 }
321 }
322
323
324 *tli = OBJ_NEW(tuple_list_item_t);
325 if (NULL == *tli) {
326 return ORTE_ERR_OUT_OF_RESOURCE;
327 }
328 (*tli)->tli_filename = strdup(filename);
329 (*tli)->tli_topic = strdup(topic);
330 opal_list_append(&abd_tuples, &((*tli)->super));
331 return ORTE_ERR_NOT_FOUND;
332 }
333
334
335 static void show_accumulated_duplicates(int fd, short event, void *context)
336 {
337 opal_list_item_t *item;
338 time_t now = time(NULL);
339 tuple_list_item_t *tli;
340 char *tmp, *output;
341
342
343
344
345 for (item = opal_list_get_first(&abd_tuples);
346 opal_list_get_end(&abd_tuples) != item;
347 item = opal_list_get_next(item)) {
348 tli = (tuple_list_item_t*) item;
349 if (tli->tli_display &&
350 tli->tli_count_since_last_display > 0) {
351 static bool first = true;
352 if (orte_xml_output) {
353 opal_asprintf(&tmp, "%d more process%s sent help message %s / %s",
354 tli->tli_count_since_last_display,
355 (tli->tli_count_since_last_display > 1) ? "es have" : " has",
356 tli->tli_filename, tli->tli_topic);
357 output = xml_format((unsigned char*)tmp);
358 free(tmp);
359 fprintf(orte_xml_fp, "%s", output);
360 free(output);
361 } else {
362 opal_output(0, "%d more process%s sent help message %s / %s",
363 tli->tli_count_since_last_display,
364 (tli->tli_count_since_last_display > 1) ? "es have" : " has",
365 tli->tli_filename, tli->tli_topic);
366 }
367 tli->tli_count_since_last_display = 0;
368
369 if (first) {
370 if (orte_xml_output) {
371 fprintf(orte_xml_fp, "<stderr>Set MCA parameter \"orte_base_help_aggregate\" to 0 to see all help / error messages</stderr>\n");
372 fflush(orte_xml_fp);
373 } else {
374 opal_output(0, "Set MCA parameter \"orte_base_help_aggregate\" to 0 to see all help / error messages");
375 }
376 first = false;
377 }
378 }
379 }
380
381 show_help_time_last_displayed = now;
382 show_help_timer_set = false;
383 }
384
385 static int show_help(const char *filename, const char *topic,
386 const char *output, orte_process_name_t *sender)
387 {
388 int rc;
389 tuple_list_item_t *tli = NULL;
390 orte_namelist_t *pnli;
391 time_t now = time(NULL);
392
393
394
395 if (orte_help_want_aggregate) {
396 rc = get_tli(filename, topic, &tli);
397 } else {
398 rc = ORTE_ERR_NOT_FOUND;
399 }
400
401
402
403 if (NULL == output) {
404 tli->tli_display = false;
405 goto after_output;
406 }
407
408
409 if (ORTE_SUCCESS == rc) {
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435 ++tli->tli_count_since_last_display;
436 if (now > show_help_time_last_displayed + 5 && !show_help_timer_set) {
437 show_accumulated_duplicates(0, 0, NULL);
438 } else if (!show_help_timer_set) {
439 opal_event_evtimer_set(orte_event_base, &show_help_timer_event,
440 show_accumulated_duplicates, NULL);
441 opal_event_evtimer_add(&show_help_timer_event, &show_help_interval);
442 show_help_timer_set = true;
443 }
444 }
445
446 else if (ORTE_ERR_NOT_FOUND == rc) {
447 if (orte_xml_output) {
448 char *tmp;
449 tmp = xml_format((unsigned char*)output);
450 fprintf(orte_xml_fp, "%s", tmp);
451 fflush(orte_xml_fp);
452 free(tmp);
453 } else {
454 opal_output(orte_help_output, "%s", output);
455 }
456 if (!show_help_timer_set) {
457 show_help_time_last_displayed = now;
458 }
459 }
460
461 else {
462 ORTE_ERROR_LOG(rc);
463 return rc;
464 }
465
466 after_output:
467
468 if (orte_help_want_aggregate) {
469 pnli = OBJ_NEW(orte_namelist_t);
470 if (NULL == pnli) {
471 rc = ORTE_ERR_OUT_OF_RESOURCE;
472 ORTE_ERROR_LOG(rc);
473 return rc;
474 }
475 pnli->name = *sender;
476 opal_list_append(&(tli->tli_processes), &(pnli->super));
477 }
478 return ORTE_SUCCESS;
479 }
480
481
482
483
484 void orte_show_help_recv(int status, orte_process_name_t* sender,
485 opal_buffer_t *buffer, orte_rml_tag_t tag,
486 void* cbdata)
487 {
488 char *output=NULL;
489 char *filename=NULL, *topic=NULL;
490 int32_t n;
491 int8_t have_output;
492 int rc;
493
494 OPAL_OUTPUT_VERBOSE((5, orte_debug_output,
495 "%s got show_help from %s",
496 ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
497 ORTE_NAME_PRINT(sender)));
498
499
500 n = 1;
501 if (ORTE_SUCCESS != (rc = opal_dss.unpack(buffer, &filename, &n, OPAL_STRING))) {
502 ORTE_ERROR_LOG(rc);
503 goto cleanup;
504 }
505
506 n = 1;
507 if (ORTE_SUCCESS != (rc = opal_dss.unpack(buffer, &topic, &n, OPAL_STRING))) {
508 ORTE_ERROR_LOG(rc);
509 goto cleanup;
510 }
511
512 n = 1;
513 if (ORTE_SUCCESS != (rc = opal_dss.unpack(buffer, &have_output, &n, OPAL_INT8))) {
514 ORTE_ERROR_LOG(rc);
515 goto cleanup;
516 }
517
518
519 if (have_output) {
520 n = 1;
521 if (ORTE_SUCCESS != (rc = opal_dss.unpack(buffer, &output, &n, OPAL_STRING))) {
522 ORTE_ERROR_LOG(rc);
523 goto cleanup;
524 }
525 }
526
527
528 rc = show_help(filename, topic, output, sender);
529
530 cleanup:
531 if (NULL != output) {
532 free(output);
533 }
534 if (NULL != filename) {
535 free(filename);
536 }
537 if (NULL != topic) {
538 free(topic);
539 }
540 }
541
542 int orte_show_help_init(void)
543 {
544 opal_output_stream_t lds;
545
546 OPAL_OUTPUT_VERBOSE((5, orte_debug_output, "orte_show_help init"));
547
548
549 if (ready) {
550 return ORTE_SUCCESS;
551 }
552
553 OBJ_CONSTRUCT(&abd_tuples, opal_list_t);
554
555
556 OBJ_CONSTRUCT(&lds, opal_output_stream_t);
557 lds.lds_want_stderr = true;
558 orte_help_output = opal_output_open(&lds);
559 OBJ_DESTRUCT(&lds);
560
561 save_help = opal_show_help;
562 opal_show_help = orte_show_help;
563 ready = true;
564
565 return ORTE_SUCCESS;
566 }
567
568 void orte_show_help_finalize(void)
569 {
570 if (!ready) {
571 return;
572 }
573 ready = false;
574
575 opal_output_close(orte_help_output);
576
577 opal_show_help = save_help;
578 save_help = NULL;
579
580
581 if (ORTE_PROC_IS_HNP) {
582 show_accumulated_duplicates(0, 0, NULL);
583 OBJ_DESTRUCT(&abd_tuples);
584 if (show_help_timer_set) {
585 opal_event_evtimer_del(&show_help_timer_event);
586 }
587
588
589 orte_rml.recv_cancel(ORTE_NAME_WILDCARD, ORTE_RML_TAG_SHOW_HELP);
590 return;
591 }
592 }
593
594 int orte_show_help(const char *filename, const char *topic,
595 int want_error_header, ...)
596 {
597 int rc = ORTE_SUCCESS;
598 va_list arglist;
599 char *output;
600
601 if (orte_execute_quiet) {
602 return ORTE_SUCCESS;
603 }
604
605 va_start(arglist, want_error_header);
606 output = opal_show_help_vstring(filename, topic, want_error_header,
607 arglist);
608 va_end(arglist);
609
610
611 if (NULL == output) {
612 return ORTE_SUCCESS;
613 }
614
615 rc = orte_show_help_norender(filename, topic, want_error_header, output);
616 free(output);
617 return rc;
618 }
619
620 static void cbfunc(int status, void *cbdata)
621 {
622 volatile bool *active = (volatile bool*)cbdata;
623 *active = false;
624 }
625
626 int orte_show_help_norender(const char *filename, const char *topic,
627 int want_error_header, const char *output)
628 {
629 int rc = ORTE_SUCCESS;
630 int8_t have_output = 1;
631 opal_buffer_t *buf;
632 bool am_inside = false;
633 opal_list_t info;
634 opal_value_t *kv;
635 volatile bool active;
636 struct timespec tp;
637
638 if (!ready) {
639
640
641
642
643
644
645
646
647
648 fprintf(stderr, "%s", output);
649 goto CLEANUP;
650 }
651
652
653
654
655
656
657 if (ORTE_PROC_IS_HNP || ORTE_PROC_IS_TOOL ||
658 orte_standalone_operation) {
659 rc = show_help(filename, topic, output, ORTE_PROC_MY_NAME);
660 goto CLEANUP;
661 } else if (ORTE_PROC_IS_DAEMON) {
662 if (NULL == orte_rml.send_buffer_nb ||
663 NULL == orte_routed.get_route ||
664 NULL == orte_process_info.my_hnp_uri) {
665 rc = show_help(filename, topic, output, ORTE_PROC_MY_NAME);
666 goto CLEANUP;
667 }
668 }
669
670
671
672
673
674
675
676
677
678 if (am_inside) {
679 rc = show_help(filename, topic, output, ORTE_PROC_MY_NAME);
680 } else {
681 am_inside = true;
682
683
684 buf = OBJ_NEW(opal_buffer_t);
685
686 opal_dss.pack(buf, &filename, 1, OPAL_STRING);
687
688 opal_dss.pack(buf, &topic, 1, OPAL_STRING);
689
690 opal_dss.pack(buf, &have_output, 1, OPAL_INT8);
691
692 opal_dss.pack(buf, &output, 1, OPAL_STRING);
693
694
695 if (ORTE_PROC_IS_DAEMON) {
696
697 if (ORTE_SUCCESS != (rc = orte_rml.send_buffer_nb(ORTE_PROC_MY_HNP, buf,
698 ORTE_RML_TAG_SHOW_HELP,
699 orte_rml_send_callback, NULL))) {
700 OBJ_RELEASE(buf);
701
702 opal_output(orte_help_output, "%s", output);
703 } else {
704 rc = ORTE_SUCCESS;
705 }
706 } else {
707
708
709 if (NULL != opal_pmix.log) {
710 OBJ_CONSTRUCT(&info, opal_list_t);
711 kv = OBJ_NEW(opal_value_t),
712 kv->key = strdup(OPAL_PMIX_LOG_MSG);
713 kv->type = OPAL_BYTE_OBJECT;
714 opal_dss.unload(buf, (void**)&kv->data.bo.bytes, &kv->data.bo.size);
715 opal_list_append(&info, &kv->super);
716 active = true;
717 tp.tv_sec = 0;
718 tp.tv_nsec = 1000000;
719 opal_pmix.log(&info, cbfunc, (void*)&active);
720 while (active) {
721 nanosleep(&tp, NULL);
722 }
723 OBJ_RELEASE(buf);
724 kv->data.bo.bytes = NULL;
725 OPAL_LIST_DESTRUCT(&info);
726 rc = ORTE_SUCCESS;
727 goto CLEANUP;
728 } else {
729 rc = show_help(filename, topic, output, ORTE_PROC_MY_NAME);
730 }
731 }
732 am_inside = false;
733 }
734
735 CLEANUP:
736 return rc;
737 }
738
739 int orte_show_help_suppress(const char *filename, const char *topic)
740 {
741 int rc = ORTE_SUCCESS;
742 int8_t have_output = 0;
743
744 if (orte_execute_quiet) {
745 return ORTE_SUCCESS;
746 }
747
748 if (!ready) {
749
750
751 return ORTE_SUCCESS;
752 }
753
754
755
756
757 if (ORTE_PROC_IS_HNP ||
758 NULL == orte_rml.send_buffer_nb ||
759 NULL == orte_routed.get_route ||
760 NULL == orte_process_info.my_hnp_uri) {
761 rc = show_help(filename, topic, NULL, ORTE_PROC_MY_NAME);
762 }
763
764
765
766
767 else {
768 opal_buffer_t *buf;
769 static bool am_inside = false;
770
771
772
773
774
775 if (am_inside) {
776 rc = show_help(filename, topic, NULL, ORTE_PROC_MY_NAME);
777 } else {
778 am_inside = true;
779
780
781 buf = OBJ_NEW(opal_buffer_t);
782
783 opal_dss.pack(buf, &filename, 1, OPAL_STRING);
784
785 opal_dss.pack(buf, &topic, 1, OPAL_STRING);
786
787 opal_dss.pack(buf, &have_output, 1, OPAL_INT8);
788
789 if (ORTE_SUCCESS != (rc = orte_rml.send_buffer_nb(ORTE_PROC_MY_HNP, buf,
790 ORTE_RML_TAG_SHOW_HELP,
791 orte_rml_send_callback, NULL))) {
792 ORTE_ERROR_LOG(rc);
793 OBJ_RELEASE(buf);
794
795 show_help(filename, topic, NULL, ORTE_PROC_MY_NAME);
796 }
797 am_inside = false;
798 }
799 }
800
801 return ORTE_SUCCESS;
802 }