root/orte/util/show_help.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. orte_show_help_is_available
  2. tuple_list_item_constructor
  3. tuple_list_item_destructor
  4. xml_format
  5. match
  6. get_tli
  7. show_accumulated_duplicates
  8. show_help
  9. orte_show_help_recv
  10. orte_show_help_init
  11. orte_show_help_finalize
  12. orte_show_help
  13. cbfunc
  14. orte_show_help_norender
  15. orte_show_help_suppress

   1 /*
   2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2006 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2008-2018 Cisco Systems, Inc.  All rights reserved.
  13  * Copyright (c) 2012-2013 Los Alamos National Security, LLC.
  14  *                         All rights reserved.
  15  * Copyright (c) 2016-2019 Intel, Inc.  All rights reserved.
  16  * Copyright (c) 2017      IBM Corporation. All rights reserved.
  17  * $COPYRIGHT$
  18  *
  19  * Additional copyrights may follow
  20  *
  21  * $HEADER$
  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  * Local variable to know whether aggregated show_help is available or
  53  * not
  54  */
  55 static bool ready = false;
  56 
  57 /*
  58  * Same for systems with or without full ORTE support
  59  */
  60 bool orte_show_help_is_available(void)
  61 {
  62     /* This is a function only to give us forward flexibility in case
  63        we need a more complicated check someday. */
  64 
  65     return ready;
  66 }
  67 
  68 /* List items for holding (filename, topic) tuples */
  69 typedef struct {
  70     opal_list_item_t super;
  71     /* The filename */
  72     char *tli_filename;
  73     /* The topic */
  74     char *tli_topic;
  75     /* List of process names that have displayed this (filename, topic) */
  76     opal_list_t tli_processes;
  77     /* Time this message was displayed */
  78     time_t tli_time_displayed;
  79     /* Count of processes since last display (i.e., "new" processes
  80        that have showed this message that have not yet been output) */
  81     int tli_count_since_last_display;
  82     /* Do we want to display these? */
  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 /* List of (filename, topic) tuples that have already been displayed */
  94 static opal_list_t abd_tuples;
  95 
  96 /* How long to wait between displaying duplicate show_help notices */
  97 static struct timeval show_help_interval = { 5, 0 };
  98 
  99 /* Timer for displaying duplicate help message notices */
 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 /* dealing with special characters in xml output */
 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     /* add some arbitrary size padding */
 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; /* default to no xml formatting */
 151     }
 152     memset(output, 0, len+1024);
 153     outlen = len+1023;
 154     endtaglen = strlen(endtag);
 155     starttaglen = strlen(starttag);
 156 
 157     /* start at the beginning */
 158     k=0;
 159 
 160     /* start with the tag */
 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, "&amp;");
 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, "&lt;");
 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, "&gt;");
 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             /* this is a non-printable character, so escape it too */
 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             /* if this was a \n, then we also need to break the line with the end tag */
 204             if ('\n' == input[i] && (k+endtaglen+1) < outlen) {
 205                 /* we need to break the line with the end tag */
 206                 for (j=0; j < endtaglen && k < outlen-1; j++) {
 207                     output[k++] = endtag[j];
 208                 }
 209                 /* move the <cr> over */
 210                 output[k++] = '\n';
 211                 /* if this isn't the end of the input buffer, add a new start tag */
 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         /* need to add an endtag */
 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     /* if we couldn't complete the processing for
 238      * some reason, return the unprocessed input
 239      * so at least the message gets out!
 240      */
 241     free(output);
 242     return (char*)input;
 243 }
 244 
 245 
 246 /*
 247  * Returns ORTE_SUCCESS if the strings match; ORTE_ERROR otherwise.
 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     /* Check straight string match first */
 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     /* No match */
 290     return ORTE_ERROR;
 291 }
 292 
 293 /*
 294  * Check to see if a given (filename, topic) tuple has been displayed
 295  * already.  Return ORTE_SUCCESS if so, or ORTE_ERR_NOT_FOUND if not.
 296  *
 297  * Always return a tuple_list_item_t representing this (filename,
 298  * topic) entry in the list of "already been displayed tuples" (if it
 299  * wasn't in the list already, this function will create a new entry
 300  * in the list and return it).
 301  *
 302  * Note that a list is not an overly-efficient mechanism for this kind
 303  * of data.  The assupmtion is that there will only be a small numebr
 304  * of (filename, topic) tuples displayed so the storage required will
 305  * be fairly small, and linear searches will be fast enough.
 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     /* Search the list for a duplicate. */
 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     /* Nope, we didn't find it -- make a new one */
 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     /* Loop through all the messages we've displayed and see if any
 343        processes have sent duplicates that have not yet been displayed
 344        yet */
 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     /* If we're aggregating, check for duplicates.  Otherwise, don't
 394        track duplicates at all and always display the message. */
 395     if (orte_help_want_aggregate) {
 396         rc = get_tli(filename, topic, &tli);
 397     } else {
 398         rc = ORTE_ERR_NOT_FOUND;
 399     }
 400 
 401     /* If there's no output string (i.e., this is a control message
 402        asking us to suppress), then skip to the end. */
 403     if (NULL == output) {
 404         tli->tli_display = false;
 405         goto after_output;
 406     }
 407 
 408     /* Was it already displayed? */
 409     if (ORTE_SUCCESS == rc) {
 410         /* Yes.  But do we want to print anything?  That's complicated.
 411 
 412            We always show the first message of a given (filename,
 413            topic) tuple as soon as it arrives.  But we don't want to
 414            show duplicate notices often, because we could get overrun
 415            with them.  So we want to gather them up and say "We got N
 416            duplicates" every once in a while.
 417 
 418            And keep in mind that at termination, we'll unconditionally
 419            show all accumulated duplicate notices.
 420 
 421            A simple scheme is as follows:
 422            - when the first of a (filename, topic) tuple arrives
 423              - print the message
 424              - if a timer is not set, set T=now
 425            - when a duplicate (filename, topic) tuple arrives
 426              - if now>(T+5) and timer is not set (due to
 427                non-pre-emptiveness of our libevent, a timer *could* be
 428                set!)
 429                - print all accumulated duplicates
 430                - reset T=now
 431              - else if a timer was not set, set the timer for T+5
 432              - else if a timer was set, do nothing (just wait)
 433            - set T=now when the timer expires
 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     /* Not already displayed */
 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     /* Some other error occurred */
 461     else {
 462         ORTE_ERROR_LOG(rc);
 463         return rc;
 464     }
 465 
 466  after_output:
 467     /* If we're aggregating, add this process name to the list */
 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 /* Note that this function is called from ess/hnp, so don't make it
 483    static */
 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     /* unpack the filename of the show_help text file */
 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     /* unpack the topic tag */
 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     /* unpack the flag */
 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     /* If we have an output string, unpack it */
 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     /* Send it to show_help */
 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     /* Show help duplicate detection */
 549     if (ready) {
 550         return ORTE_SUCCESS;
 551     }
 552 
 553     OBJ_CONSTRUCT(&abd_tuples, opal_list_t);
 554 
 555     /* create an output stream for us */
 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     /* Shutdown show_help, showing final messages */
 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         /* cancel the recv */
 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     /* If nothing came back, there's nothing to do */
 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         /* if we are finalizing, then we have no way to process
 640          * this through the orte_show_help system - just drop it to
 641          * stderr; that's at least better than not showing it.
 642          *
 643          * If we are not finalizing, then this is probably a show_help
 644          * stemming from either a cmd-line request to display the usage
 645          * message, or a show_help related to a user error. In either case,
 646          * we can't do anything but just print to stderr.
 647          */
 648         fprintf(stderr, "%s", output);
 649         goto CLEANUP;
 650     }
 651 
 652     /* if we are the HNP, or the RML has not yet been setup,
 653      * or ROUTED has not been setup,
 654      * or we weren't given an HNP, or we are running in standalone
 655      * mode, then all we can do is process this locally
 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     /* otherwise, we relay the output message to
 671      * the HNP for processing
 672      */
 673 
 674     /* JMS Note that we *may* have a recursion situation here where
 675        the RML could call show_help.  Need to think about this
 676        properly, but put a safeguard in here for sure for the time
 677        being. */
 678     if (am_inside) {
 679         rc = show_help(filename, topic, output, ORTE_PROC_MY_NAME);
 680     } else {
 681         am_inside = true;
 682 
 683         /* build the message to the HNP */
 684         buf = OBJ_NEW(opal_buffer_t);
 685         /* pack the filename of the show_help text file */
 686         opal_dss.pack(buf, &filename, 1, OPAL_STRING);
 687         /* pack the topic tag */
 688         opal_dss.pack(buf, &topic, 1, OPAL_STRING);
 689         /* pack the flag that we have a string */
 690         opal_dss.pack(buf, &have_output, 1, OPAL_INT8);
 691         /* pack the resulting string */
 692         opal_dss.pack(buf, &output, 1, OPAL_STRING);
 693 
 694         /* if we are a daemon, then send it via RML to the HNP */
 695         if (ORTE_PROC_IS_DAEMON) {
 696             /* send it to the HNP */
 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                 /* okay, that didn't work, output locally  */
 702                 opal_output(orte_help_output, "%s", output);
 703             } else {
 704                 rc = ORTE_SUCCESS;
 705             }
 706         } else {
 707             /* if we are not a daemon (i.e., we are an app) and if PMIx
 708              * support for "log" is available, then use that channel */
 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         /* If we are finalizing, then we have no way to process this
 750            through the orte_show_help system - just drop it. */
 751         return ORTE_SUCCESS;
 752     }
 753 
 754     /* If we are the HNP, or the RML has not yet been setup, or ROUTED
 755        has not been setup, or we weren't given an HNP, then all we can
 756        do is process this locally. */
 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     /* otherwise, we relay the output message to
 765      * the HNP for processing
 766      */
 767     else {
 768         opal_buffer_t *buf;
 769         static bool am_inside = false;
 770 
 771         /* JMS Note that we *may* have a recursion situation here where
 772            the RML could call show_help.  Need to think about this
 773            properly, but put a safeguard in here for sure for the time
 774            being. */
 775         if (am_inside) {
 776             rc = show_help(filename, topic, NULL, ORTE_PROC_MY_NAME);
 777         } else {
 778             am_inside = true;
 779 
 780             /* build the message to the HNP */
 781             buf = OBJ_NEW(opal_buffer_t);
 782             /* pack the filename of the show_help text file */
 783             opal_dss.pack(buf, &filename, 1, OPAL_STRING);
 784             /* pack the topic tag */
 785             opal_dss.pack(buf, &topic, 1, OPAL_STRING);
 786             /* pack the flag that we DO NOT have a string */
 787             opal_dss.pack(buf, &have_output, 1, OPAL_INT8);
 788             /* send it to the HNP */
 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                 /* okay, that didn't work, just process locally error, just ignore return  */
 795                 show_help(filename, topic, NULL, ORTE_PROC_MY_NAME);
 796             }
 797             am_inside = false;
 798         }
 799     }
 800 
 801     return ORTE_SUCCESS;
 802 }

/* [<][>][^][v][top][bottom][index][help] */