openmpi  3.1.6
About: Open MPI is a high performance Message Passing Interface (MPI) library project combining technologies and resources from several other projects (FT-MPI, LA-MPI, LAM/MPI, and PACX-MPI) in order to build the best MPI library available. 3.x series.
  Fossies Dox: openmpi-3.1.6.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

output.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana
3  * University Research and Technology
4  * Corporation. All rights reserved.
5  * Copyright (c) 2004-2008 The University of Tennessee and The University
6  * of Tennessee Research Foundation. All rights
7  * reserved.
8  * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart,
9  * University of Stuttgart. All rights reserved.
10  * Copyright (c) 2004-2006 The Regents of the University of California.
11  * All rights reserved.
12  * Copyright (c) 2007-2008 Cisco Systems, Inc. All rights reserved.
13  * Copyright (c) 2014-2019 Intel, Inc. All rights reserved.
14  * Copyright (c) 2015 Research Organization for Information Science
15  * and Technology (RIST). All rights reserved.
16  * $COPYRIGHT$
17  *
18  * Additional copyrights may follow
19  *
20  * $HEADER$
21  */
22 
23 #include <src/include/pmix_config.h>
24 
25 #include <pmix_common.h>
26 
27 #include <stdio.h>
28 #include <ctype.h>
29 #include <stdarg.h>
30 #include <stdlib.h>
31 #ifdef HAVE_SYSLOG_H
32 #include <syslog.h>
33 #endif
34 #include <string.h>
35 #include <fcntl.h>
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 #ifdef HAVE_SYS_PARAM_H
40 #include <sys/param.h>
41 #endif
42 
43 #include "src/util/pmix_environ.h"
44 #include "src/util/error.h"
45 #include "src/util/output.h"
46 
47 /*
48  * Private data
49  */
50 static int verbose_stream = -1;
52 static char *output_dir = NULL;
53 static char *output_prefix = NULL;
54 
55 
56 /*
57  * Internal data structures and helpers for the generalized output
58  * stream mechanism.
59  */
60 typedef struct {
61  bool ldi_used;
64 
65  bool ldi_syslog;
67 
69  char *ldi_prefix;
71 
72  char *ldi_suffix;
74 
75  bool ldi_stdout;
76  bool ldi_stderr;
77 
78  bool ldi_file;
81  int ldi_fd;
84 
85 /*
86  * Private functions
87  */
88 static void construct(pmix_object_t *stream);
89 static void destruct(pmix_object_t *stream);
90 static int do_open(int output_id, pmix_output_stream_t * lds);
91 static int open_file(int i);
92 static void free_descriptor(int output_id);
93 static int make_string(char **out, char **no_newline_string, output_desc_t *ldi,
94  const char *format, va_list arglist);
95 static int output(int output_id, const char *format, va_list arglist);
96 
97 
98 #define PMIX_OUTPUT_MAX_STREAMS 64
99 #if defined(HAVE_SYSLOG)
100 #define USE_SYSLOG 1
101 #else
102 #define USE_SYSLOG 0
103 #endif
104 
105 /* global state */
108 
109 /*
110  * Local state
111  */
112 static bool initialized = false;
113 static int default_stderr_fd = -1;
115 #if defined(HAVE_SYSLOG)
116 static bool syslog_opened = false;
117 #endif
119 
121 
122 /*
123  * Setup the output stream infrastructure
124  */
126 {
127  int i;
128  char hostname[PMIX_MAXHOSTNAMELEN] = {0};
129  char *str;
130 
131  if (initialized) {
132  return true;
133  }
134 
135  str = getenv("PMIX_OUTPUT_STDERR_FD");
136  if (NULL != str) {
137  default_stderr_fd = atoi(str);
138  }
139  str = getenv("PMIX_OUTPUT_REDIRECT");
140  if (NULL != str) {
141  if (0 == strcasecmp(str, "syslog")) {
143  }
144  }
145  str = getenv("PMIX_OUTPUT_SYSLOG_PRI");
146 #ifdef HAVE_SYSLOG_H
147  if (NULL != str) {
148  if (0 == strcasecmp(str, "info")) {
150  } else if (0 == strcasecmp(str, "error")) {
152  } else if (0 == strcasecmp(str, "warn")) {
153  pmix_output_redirected_syslog_pri = LOG_WARNING;
154  } else {
156  }
157  } else {
159  }
160 #endif
161 
162  str = getenv("PMIX_OUTPUT_SYSLOG_IDENT");
163  if (NULL != str) {
164  redirect_syslog_ident = strdup(str);
165  }
166 
169  verbose.lds_want_syslog = true;
171  if (NULL != str) {
173  }
174  verbose.lds_want_stderr = false;
175  verbose.lds_want_stdout = false;
176  } else {
177  verbose.lds_want_stderr = true;
178  }
179  gethostname(hostname, sizeof(hostname)-1);
180  hostname[sizeof(hostname)-1] = '\0';
181  if (0 > asprintf(&verbose.lds_prefix, "[%s:%05d] ", hostname, getpid())) {
182  return PMIX_ERR_NOMEM;
183  }
184 
185  for (i = 0; i < PMIX_OUTPUT_MAX_STREAMS; ++i) {
186  info[i].ldi_used = false;
187  info[i].ldi_enabled = false;
188 
190  info[i].ldi_file = false;
192  info[i].ldi_file_want_append = false;
193  info[i].ldi_fd = -1;
195  }
196 
197 
198  initialized = true;
199 
200  /* Set some defaults */
201 
202  if (0 > asprintf(&output_prefix, "output-pid%d-", getpid())) {
203  return false;
204  }
205  output_dir = strdup(pmix_tmp_directory());
206 
207  /* Open the default verbose stream */
209  return true;
210 }
211 
212 
213 /*
214  * Open a stream
215  */
217 {
218  return do_open(-1, lds);
219 }
220 
221 
222 /*
223  * Reset the parameters on a stream
224  */
225 int pmix_output_reopen(int output_id, pmix_output_stream_t * lds)
226 {
227  return do_open(output_id, lds);
228 }
229 
230 
231 /*
232  * Enable and disable output streams
233  */
234 bool pmix_output_switch(int output_id, bool enable)
235 {
236  bool ret = false;
237 
238  /* Setup */
239 
240  if (!initialized) {
242  }
243 
244  if (output_id >= 0 && output_id < PMIX_OUTPUT_MAX_STREAMS) {
245  ret = info[output_id].ldi_enabled;
246  info[output_id].ldi_enabled = enable;
247  }
248 
249  return ret;
250 }
251 
252 
253 /*
254  * Reopen all the streams; used during checkpoint/restart.
255  */
257 {
258  char *str;
259  char hostname[PMIX_MAXHOSTNAMELEN] = {0};
260 
261  str = getenv("PMIX_OUTPUT_STDERR_FD");
262  if (NULL != str) {
263  default_stderr_fd = atoi(str);
264  } else {
265  default_stderr_fd = -1;
266  }
267 
268  gethostname(hostname, sizeof(hostname));
269  if( NULL != verbose.lds_prefix ) {
272  }
273  if (0 > asprintf(&verbose.lds_prefix, "[%s:%05d] ", hostname, getpid())) {
275  return;
276  }
277 }
278 
279 
280 /*
281  * Close a stream
282  */
283 void pmix_output_close(int output_id)
284 {
285  int i;
286 
287  /* Setup */
288 
289  if (!initialized) {
290  return;
291  }
292 
293  /* If it's valid, used, enabled, and has an open file descriptor,
294  * free the resources associated with the descriptor */
295 
296  if (output_id >= 0 && output_id < PMIX_OUTPUT_MAX_STREAMS &&
297  info[output_id].ldi_used && info[output_id].ldi_enabled) {
298  free_descriptor(output_id);
299 
300  /* If no one has the syslog open, we should close it */
301 
302  for (i = 0; i < PMIX_OUTPUT_MAX_STREAMS; ++i) {
303  if (info[i].ldi_used && info[i].ldi_syslog) {
304  break;
305  }
306  }
307 
308 #if defined(HAVE_SYSLOG)
309  if (i >= PMIX_OUTPUT_MAX_STREAMS && syslog_opened) {
310  closelog();
311  }
312 #endif
313  }
314 
315 }
316 
317 
318 /*
319  * Main function to send output to a stream
320  */
321 PMIX_EXPORT void pmix_output(int output_id, const char *format, ...)
322 {
323  if (output_id >= 0 && output_id < PMIX_OUTPUT_MAX_STREAMS) {
324  va_list arglist;
325  va_start(arglist, format);
326  output(output_id, format, arglist);
327  va_end(arglist);
328  }
329 }
330 
331 
332 /*
333  * Send a message to a stream if the verbose level is high enough
334  */
335  PMIX_EXPORT void pmix_output_verbose(int level, int output_id, const char *format, ...)
336 {
337  if (output_id >= 0 && output_id < PMIX_OUTPUT_MAX_STREAMS &&
338  info[output_id].ldi_verbose_level >= level) {
339  va_list arglist;
340  va_start(arglist, format);
341  output(output_id, format, arglist);
342  va_end(arglist);
343  }
344 }
345 
346 
347 /*
348  * Send a message to a stream if the verbose level is high enough
349  */
350 void pmix_output_vverbose(int level, int output_id, const char *format,
351  va_list arglist)
352 {
353  if (output_id >= 0 && output_id < PMIX_OUTPUT_MAX_STREAMS &&
354  info[output_id].ldi_verbose_level >= level) {
355  output(output_id, format, arglist);
356  }
357 }
358 
359 
360 /*
361  * Set the verbosity level of a stream
362  */
363 void pmix_output_set_verbosity(int output_id, int level)
364 {
365  if (output_id >= 0 && output_id < PMIX_OUTPUT_MAX_STREAMS) {
366  info[output_id].ldi_verbose_level = level;
367  }
368 }
369 
370 
371 /*
372  * Control where output flies will go
373  */
374 void pmix_output_set_output_file_info(const char *dir,
375  const char *prefix,
376  char **olddir,
377  char **oldprefix)
378 {
379  if (NULL != olddir) {
380  *olddir = strdup(output_dir);
381  }
382  if (NULL != oldprefix) {
383  *oldprefix = strdup(output_prefix);
384  }
385 
386  if (NULL != dir) {
387  free(output_dir);
388  output_dir = strdup(dir);
389  }
390  if (NULL != prefix) {
392  output_prefix = strdup(prefix);
393  }
394 }
395 
396 void pmix_output_hexdump(int verbose_level, int output_id,
397  void *ptr, int buflen)
398 {
399  unsigned char *buf = (unsigned char *) ptr;
400  char out_buf[120];
401  int ret = 0;
402  int out_pos = 0;
403  int i, j;
404 
405  if (output_id >= 0 && output_id < PMIX_OUTPUT_MAX_STREAMS &&
406  info[output_id].ldi_verbose_level >= verbose_level) {
407  pmix_output_verbose(verbose_level, output_id, "dump data at %p %d bytes\n", ptr, buflen);
408  for (i = 0; i < buflen; i += 16) {
409  out_pos = 0;
410  ret = sprintf(out_buf + out_pos, "%06x: ", i);
411  if (ret < 0)
412  return;
413  out_pos += ret;
414  for (j = 0; j < 16; j++) {
415  if (i + j < buflen)
416  ret = sprintf(out_buf + out_pos, "%02x ",
417  buf[i + j]);
418  else
419  ret = sprintf(out_buf + out_pos, " ");
420  if (ret < 0)
421  return;
422  out_pos += ret;
423  }
424  ret = sprintf(out_buf + out_pos, " ");
425  if (ret < 0)
426  return;
427  out_pos += ret;
428  for (j = 0; j < 16; j++)
429  if (i + j < buflen) {
430  ret = sprintf(out_buf + out_pos, "%c",
431  isprint(buf[i+j]) ?
432  buf[i + j] :
433  '.');
434  if (ret < 0)
435  return;
436  out_pos += ret;
437  }
438  ret = sprintf(out_buf + out_pos, "\n");
439  if (ret < 0)
440  return;
441  pmix_output_verbose(verbose_level, output_id, "%s", out_buf);
442  }
443  }
444 }
445 
446 
447 /*
448  * Shut down the output stream system
449  */
451 {
452  if (initialized) {
453  if (verbose_stream != -1) {
455  }
457  verbose_stream = -1;
458 
460  free (output_dir);
462  }
463 }
464 
465 
467 /*
468  * Constructor
469  */
470 static void construct(pmix_object_t *obj)
471 {
473 
474  stream->lds_verbose_level = 0;
475  stream->lds_syslog_priority = 0;
476  stream->lds_syslog_ident = NULL;
477  stream->lds_prefix = NULL;
478  stream->lds_suffix = NULL;
479  stream->lds_is_debugging = false;
480  stream->lds_want_syslog = false;
481  stream->lds_want_stdout = false;
482  stream->lds_want_stderr = false;
483  stream->lds_want_file = false;
484  stream->lds_want_file_append = false;
485  stream->lds_file_suffix = NULL;
486 }
487 static void destruct(pmix_object_t *obj)
488 {
490 
491  if( NULL != stream->lds_file_suffix ) {
492  free(stream->lds_file_suffix);
493  stream->lds_file_suffix = NULL;
494  }
495 }
496 
497 /*
498  * Back-end of open() and reopen().
499  */
500 static int do_open(int output_id, pmix_output_stream_t * lds)
501 {
502  int i;
503  bool redirect_to_file = false;
504  char *str, *sfx;
505 
506  /* Setup */
507 
508  if (!initialized) {
510  }
511 
512  str = getenv("PMIX_OUTPUT_REDIRECT");
513  if (NULL != str && 0 == strcasecmp(str, "file")) {
514  redirect_to_file = true;
515  }
516  sfx = getenv("PMIX_OUTPUT_SUFFIX");
517 
518  /* If output_id == -1, find an available stream, or return
519  * PMIX_ERROR */
520 
521  if (-1 == output_id) {
522  for (i = 0; i < PMIX_OUTPUT_MAX_STREAMS; ++i) {
523  if (!info[i].ldi_used) {
524  break;
525  }
526  }
527  if (i >= PMIX_OUTPUT_MAX_STREAMS) {
528  return PMIX_ERR_OUT_OF_RESOURCE;
529  }
530  }
531 
532  /* Otherwise, we're reopening, so we need to free all previous
533  * resources, close files, etc. */
534 
535  else {
536  free_descriptor(output_id);
537  i = output_id;
538  }
539 
540  /* Special case: if we got NULL for lds, then just use the default
541  * verbose */
542 
543  if (NULL == lds) {
544  lds = &verbose;
545  }
546 
547  /* Got a stream -- now initialize it and open relevant outputs */
548 
549  info[i].ldi_used = true;
550  info[i].ldi_enabled = lds->lds_is_debugging ?
551  (bool) PMIX_ENABLE_DEBUG : true;
553 
554 #if USE_SYSLOG
555 #if defined(HAVE_SYSLOG)
557  info[i].ldi_syslog = true;
559  if (NULL != redirect_syslog_ident) {
561  openlog(redirect_syslog_ident, LOG_PID, LOG_USER);
562  } else {
564  openlog("pmix", LOG_PID, LOG_USER);
565  }
566  syslog_opened = true;
567  } else {
568 #endif
569  info[i].ldi_syslog = lds->lds_want_syslog;
570  if (lds->lds_want_syslog) {
571 
572 #if defined(HAVE_SYSLOG)
573  if (NULL != lds->lds_syslog_ident) {
574  info[i].ldi_syslog_ident = strdup(lds->lds_syslog_ident);
575  openlog(lds->lds_syslog_ident, LOG_PID, LOG_USER);
576  } else {
578  openlog("pmix", LOG_PID, LOG_USER);
579  }
580 #endif
581  syslog_opened = true;
583  }
584 
585 #if defined(HAVE_SYSLOG)
586  }
587 #endif
588 
589 #else
590  info[i].ldi_syslog = false;
591 #endif
592 
593  if (NULL != lds->lds_prefix) {
594  info[i].ldi_prefix = strdup(lds->lds_prefix);
595  info[i].ldi_prefix_len = (int)strlen(lds->lds_prefix);
596  } else {
597  info[i].ldi_prefix = NULL;
598  info[i].ldi_prefix_len = 0;
599  }
600 
601  if (NULL != lds->lds_suffix) {
602  info[i].ldi_suffix = strdup(lds->lds_suffix);
603  info[i].ldi_suffix_len = (int)strlen(lds->lds_suffix);
604  } else {
605  info[i].ldi_suffix = NULL;
606  info[i].ldi_suffix_len = 0;
607  }
608 
610  /* since all is redirected to syslog, ensure
611  * we don't duplicate the output to the std places
612  */
613  info[i].ldi_stdout = false;
614  info[i].ldi_stderr = false;
615  info[i].ldi_file = false;
616  info[i].ldi_fd = -1;
617  } else {
618  /* since we aren't redirecting to syslog, use what was
619  * given to us
620  */
621  if (NULL != str && redirect_to_file) {
622  info[i].ldi_stdout = false;
623  info[i].ldi_stderr = false;
624  info[i].ldi_file = true;
625  } else {
626  info[i].ldi_stdout = lds->lds_want_stdout;
627  info[i].ldi_stderr = lds->lds_want_stderr;
628 
629  info[i].ldi_fd = -1;
630  info[i].ldi_file = lds->lds_want_file;
631  }
632  if (NULL != sfx) {
633  info[i].ldi_file_suffix = strdup(sfx);
634  } else {
635  info[i].ldi_file_suffix = (NULL == lds->lds_file_suffix) ? NULL :
636  strdup(lds->lds_file_suffix);
637  }
640  }
641 
642  /* Don't open a file in the session directory now -- do that lazily
643  * so that if there's no output, we don't have an empty file */
644 
645  return i;
646 }
647 
648 
649 static int open_file(int i)
650 {
651  int flags;
652  char *filename;
653  int n;
654 
655  /* first check to see if this file is already open
656  * on someone else's stream - if so, we don't want
657  * to open it twice
658  */
659  for (n=0; n < PMIX_OUTPUT_MAX_STREAMS; n++) {
660  if (i == n) {
661  continue;
662  }
663  if (!info[n].ldi_used) {
664  continue;
665  }
666  if (!info[n].ldi_file) {
667  continue;
668  }
669  if (NULL != info[i].ldi_file_suffix &&
670  NULL != info[n].ldi_file_suffix) {
671  if (0 != strcmp(info[i].ldi_file_suffix, info[n].ldi_file_suffix)) {
672  break;
673  }
674  }
675  if (NULL == info[i].ldi_file_suffix &&
676  NULL != info[n].ldi_file_suffix) {
677  break;
678  }
679  if (NULL != info[i].ldi_file_suffix &&
680  NULL == info[n].ldi_file_suffix) {
681  break;
682  }
683  if (info[n].ldi_fd < 0) {
684  break;
685  }
686  info[i].ldi_fd = info[n].ldi_fd;
687  return PMIX_SUCCESS;
688  }
689 
690  /* Setup the filename and open flags */
691 
692  if (NULL != output_dir) {
693  filename = (char *) malloc(PMIX_PATH_MAX);
694  if (NULL == filename) {
695  return PMIX_ERR_OUT_OF_RESOURCE;
696  }
697  pmix_strncpy(filename, output_dir, PMIX_PATH_MAX-1);
698  strcat(filename, "/");
699  if (NULL != output_prefix) {
700  strcat(filename, output_prefix);
701  }
702  if (info[i].ldi_file_suffix != NULL) {
703  strcat(filename, info[i].ldi_file_suffix);
704  } else {
706  strcat(filename, "output.txt");
707  }
708  flags = O_CREAT | O_RDWR;
709  if (!info[i].ldi_file_want_append) {
710  flags |= O_TRUNC;
711  }
712 
713  /* Actually open the file */
714  info[i].ldi_fd = open(filename, flags, 0644);
715  free(filename); /* release the filename in all cases */
716  if (-1 == info[i].ldi_fd) {
717  info[i].ldi_used = false;
718  return PMIX_ERR_IN_ERRNO;
719  }
720 
721  /* Make the file be close-on-exec to prevent child inheritance
722  * problems */
723  if (-1 == fcntl(info[i].ldi_fd, F_SETFD, 1)) {
724  return PMIX_ERR_IN_ERRNO;
725  }
726 
727  }
728 
729  /* Return successfully even if the session dir did not exist yet;
730  * we'll try opening it later */
731 
732  return PMIX_SUCCESS;
733 }
734 
735 
736 /*
737  * Free all the resources associated with a descriptor.
738  */
739 static void free_descriptor(int output_id)
740 {
741  output_desc_t *ldi;
742 
743  if (output_id >= 0 && output_id < PMIX_OUTPUT_MAX_STREAMS &&
744  info[output_id].ldi_used && info[output_id].ldi_enabled) {
745  ldi = &info[output_id];
746 
747  if (-1 != ldi->ldi_fd) {
748  close(ldi->ldi_fd);
749  }
750  ldi->ldi_used = false;
751 
752  /* If we strduped a prefix, suffix, or syslog ident, free it */
753 
754  if (NULL != ldi->ldi_prefix) {
755  free(ldi->ldi_prefix);
756  }
757  ldi->ldi_prefix = NULL;
758 
759  if (NULL != ldi->ldi_suffix) {
760  free(ldi->ldi_suffix);
761  }
762  ldi->ldi_suffix = NULL;
763 
764  if (NULL != ldi->ldi_file_suffix) {
765  free(ldi->ldi_file_suffix);
766  }
767  ldi->ldi_file_suffix = NULL;
768 
769  if (NULL != ldi->ldi_syslog_ident) {
770  free(ldi->ldi_syslog_ident);
771  }
772  ldi->ldi_syslog_ident = NULL;
773  }
774 }
775 
776 
777 static int make_string(char **out, char **no_newline_string, output_desc_t *ldi,
778  const char *format, va_list arglist)
779 {
780  size_t len, total_len, temp_str_len;
781  bool want_newline = false;
782  char *temp_str;
783 
784  /* Make the formatted string */
785  *out = NULL;
786  if (0 > vasprintf(no_newline_string, format, arglist)) {
787  return PMIX_ERR_NOMEM;
788  }
789  total_len = len = strlen(*no_newline_string);
790  if ('\n' != (*no_newline_string)[len - 1]) {
791  want_newline = true;
792  ++total_len;
793  } else if (NULL != ldi->ldi_suffix) {
794  /* if we have a suffix, then we don't want a
795  * newline to appear before it
796  */
797  (*no_newline_string)[len - 1] = '\0';
798  want_newline = true; /* add newline to end after suffix */
799  /* total_len won't change since we just moved the newline
800  * to appear after the suffix
801  */
802  }
803  if (NULL != ldi->ldi_prefix) {
804  total_len += strlen(ldi->ldi_prefix);
805  }
806  if (NULL != ldi->ldi_suffix) {
807  total_len += strlen(ldi->ldi_suffix);
808  }
809  temp_str = (char *) malloc(total_len * 2);
810  if (NULL == temp_str) {
811  return PMIX_ERR_OUT_OF_RESOURCE;
812  }
813  temp_str_len = total_len * 2;
814  if (NULL != ldi->ldi_prefix && NULL != ldi->ldi_suffix) {
815  if (want_newline) {
816  snprintf(temp_str, temp_str_len, "%s%s%s\n",
817  ldi->ldi_prefix, *no_newline_string, ldi->ldi_suffix);
818  } else {
819  snprintf(temp_str, temp_str_len, "%s%s%s", ldi->ldi_prefix,
820  *no_newline_string, ldi->ldi_suffix);
821  }
822  } else if (NULL != ldi->ldi_prefix) {
823  if (want_newline) {
824  snprintf(temp_str, temp_str_len, "%s%s\n",
825  ldi->ldi_prefix, *no_newline_string);
826  } else {
827  snprintf(temp_str, temp_str_len, "%s%s", ldi->ldi_prefix,
828  *no_newline_string);
829  }
830  } else if (NULL != ldi->ldi_suffix) {
831  if (want_newline) {
832  snprintf(temp_str, temp_str_len, "%s%s\n",
833  *no_newline_string, ldi->ldi_suffix);
834  } else {
835  snprintf(temp_str, temp_str_len, "%s%s",
836  *no_newline_string, ldi->ldi_suffix);
837  }
838  } else {
839  if (want_newline) {
840  snprintf(temp_str, temp_str_len, "%s\n", *no_newline_string);
841  } else {
842  snprintf(temp_str, temp_str_len, "%s", *no_newline_string);
843  }
844  }
845  *out = temp_str;
846  return PMIX_SUCCESS;
847 }
848 
849 /*
850  * Do the actual output. Take a va_list so that we can be called from
851  * multiple different places, even functions that took "..." as input
852  * arguments.
853  */
854 static int output(int output_id, const char *format, va_list arglist)
855 {
856  int rc = PMIX_SUCCESS;
857  char *str=NULL, *out = NULL;
858  output_desc_t *ldi;
859 
860  /* Setup */
861 
862  if (!initialized) {
864  }
865 
866  /* If it's valid, used, and enabled, output */
867 
868  if (output_id >= 0 && output_id < PMIX_OUTPUT_MAX_STREAMS &&
869  info[output_id].ldi_used && info[output_id].ldi_enabled) {
870  ldi = &info[output_id];
871 
872  /* Make the strings */
873  if (PMIX_SUCCESS != (rc = make_string(&out, &str, ldi, format, arglist))) {
874  goto cleanup;
875  }
876 
877  /* Syslog output -- does not use the newline-appended string */
878 #if defined(HAVE_SYSLOG)
879  if (ldi->ldi_syslog) {
880  syslog(ldi->ldi_syslog_priority, "%s", str);
881  }
882 #endif
883 
884  /* stdout output */
885  if (ldi->ldi_stdout) {
886  if (0 > write(fileno(stdout), out, (int)strlen(out))) {
887  rc = PMIX_ERROR;
888  goto cleanup;
889  }
890  fflush(stdout);
891  }
892 
893  /* stderr output */
894  if (ldi->ldi_stderr) {
895  if (0 > write((-1 == default_stderr_fd) ?
896  fileno(stderr) : default_stderr_fd,
897  out, (int)strlen(out))) {
898  rc = PMIX_ERROR;
899  goto cleanup;
900  }
901  fflush(stderr);
902  }
903 
904  /* File output -- first check to see if the file opening was
905  * delayed. If so, try to open it. If we failed to open it,
906  * then just discard (there are big warnings in the
907  * pmix_output.h docs about this!). */
908 
909  if (ldi->ldi_file) {
910  if (ldi->ldi_fd == -1) {
911  if (PMIX_SUCCESS != open_file(output_id)) {
913  } else if (ldi->ldi_file_num_lines_lost > 0 && 0 <= ldi->ldi_fd) {
914  char buffer[BUFSIZ];
915  char *out = buffer;
916  memset(buffer, 0, BUFSIZ);
917  snprintf(buffer, BUFSIZ - 1,
918  "[WARNING: %d lines lost because the PMIx process session directory did\n not exist when pmix_output() was invoked]\n",
920  if (0 > write(ldi->ldi_fd, buffer, (int)strlen(buffer))) {
921  rc = PMIX_ERROR;
922  goto cleanup;
923  }
924  ldi->ldi_file_num_lines_lost = 0;
925  if (out != buffer) {
926  free(out);
927  }
928  }
929  }
930  if (ldi->ldi_fd != -1) {
931  if (0 > write(ldi->ldi_fd, out, (int)strlen(out))) {
932  rc = PMIX_ERROR;
933  goto cleanup;
934  }
935  }
936  }
937  free(str);
938  str = NULL;
939  }
940 
941  cleanup:
942  if (NULL != str) {
943  free(str);
944  }
945  if (NULL != out) {
946  free(out);
947  }
948  return rc;
949 }
950 
951 int pmix_output_get_verbosity(int output_id)
952 {
953  if (output_id >= 0 && output_id < PMIX_OUTPUT_MAX_STREAMS && info[output_id].ldi_used) {
954  return info[output_id].ldi_verbose_level;
955  } else {
956  return -1;
957  }
958 }
pmix_object_t
Base object.
Definition: pmix_object.h:188
pmix_output_stream_t::lds_syslog_priority
int lds_syslog_priority
When pmix_output_stream_t::lds_want_syslog is true, this field is examined to see what priority outpu...
Definition: output.h:144
pmix_output_hexdump
void pmix_output_hexdump(int verbose_level, int output_id, void *ptr, int buflen)
Same as pmix_output_verbose(), but pointer to buffer and size.
Definition: output.c:396
pmix_output_verbose
PMIX_EXPORT void pmix_output_verbose(int level, int output_id, const char *format,...)
Definition: output.c:335
output_desc_t::ldi_fd
int ldi_fd
Definition: output.c:81
pmix_output_vverbose
void pmix_output_vverbose(int level, int output_id, const char *format, va_list arglist)
Definition: output.c:350
pmix_output_stream_t::lds_file_suffix
char * lds_file_suffix
When pmix_output_stream_t::lds_want_file is true, this field indicates the string suffix to add to th...
Definition: output.h:248
output_desc_t::ldi_syslog_ident
char * ldi_syslog_ident
Definition: output.c:68
verbose_level
static int verbose_level
Definition: tm_bucket.c:32
open_file
static int open_file(int i)
Definition: output.c:649
info
static output_desc_t info[64]
Definition: output.c:114
pmix_output_redirected_to_syslog
bool pmix_output_redirected_to_syslog
Definition: output.c:106
pmix_output_get_verbosity
int pmix_output_get_verbosity(int output_id)
Get the verbosity level for a stream.
Definition: output.c:951
pmix_output_stream_t::lds_verbose_level
int lds_verbose_level
Indicate the starting verbosity level of the stream.
Definition: output.h:133
default_stderr_fd
static int default_stderr_fd
Definition: output.c:113
PMIX_OUTPUT_MAX_STREAMS
#define PMIX_OUTPUT_MAX_STREAMS
Definition: output.c:98
verbose_stream
static int verbose_stream
Definition: output.c:50
output_desc_t::ldi_file
bool ldi_file
Definition: output.c:78
redirect_syslog_ident
static char * redirect_syslog_ident
Definition: output.c:118
pmix_output_set_output_file_info
void pmix_output_set_output_file_info(const char *dir, const char *prefix, char **olddir, char **oldprefix)
Set characteristics for output files.
Definition: output.c:374
prefix
char * prefix
Definition: orte-dvm.c:104
pmix_output_stream_t
Definition: output.h:117
cleanup
static void cleanup(int sd, short args, void *cbdata)
Definition: rml_base_frame.c:85
output_desc_t::ldi_syslog_priority
int ldi_syslog_priority
Definition: output.c:66
output_desc_t::ldi_stderr
bool ldi_stderr
Definition: output.c:76
pmix_output_stream_t::lds_suffix
char * lds_suffix
String suffix added to all output on the stream.
Definition: output.h:177
pmix_output_stream_t::lds_want_stderr
bool lds_want_stderr
Whether to send stream output to stderr or not.
Definition: output.h:215
verbose
static pmix_output_stream_t verbose
Definition: output.c:51
output_desc_t::ldi_file_num_lines_lost
int ldi_file_num_lines_lost
Definition: output.c:82
output_desc_t::ldi_suffix_len
int ldi_suffix_len
Definition: output.c:73
output_desc_t::ldi_prefix_len
int ldi_prefix_len
Definition: output.c:70
pmix_environ.h
output_desc_t
Definition: output.c:60
temp_str_len
static size_t temp_str_len
Definition: output.c:117
pmix_output_switch
bool pmix_output_switch(int output_id, bool enable)
Enables and disables output streams.
Definition: output.c:234
pmix_output_reopen_all
void pmix_output_reopen_all(void)
Definition: output.c:256
output_desc_t::ldi_enabled
bool ldi_enabled
Definition: output.c:62
output_desc_t::ldi_file_suffix
char * ldi_file_suffix
Definition: output.c:80
output_desc_t::ldi_stdout
bool ldi_stdout
Definition: output.c:75
PMIX_PATH_MAX
#define PMIX_PATH_MAX
Definition: pmix_config_bottom.h:393
output_dir
static char * output_dir
Definition: output.c:52
output_desc_t::ldi_file_want_append
bool ldi_file_want_append
Definition: output.c:79
output_desc_t::ldi_suffix
char * ldi_suffix
Definition: output.c:72
pmix_output_init
bool pmix_output_init(void)
Initializes the output stream system and opens a default "verbose" stream.
Definition: output.c:125
output.h
pmix_output_stream_t::lds_want_stdout
bool lds_want_stdout
Whether to send stream output to stdout or not.
Definition: output.h:209
snprintf
#define snprintf
Definition: pmix_config_bottom.h:428
asprintf
#define asprintf
Definition: pmix_config_bottom.h:424
error.h
PMIX_CONSTRUCT
#define PMIX_CONSTRUCT(object, type)
Construct (initialize) objects that are not dynamically allocated.
Definition: pmix_object.h:348
PMIX_CLASS_INSTANCE
PMIX_CLASS_INSTANCE(pmix_output_stream_t, pmix_object_t, construct, destruct)
temp_str
static char * temp_str
Definition: output.c:116
pmix_output_stream_t::lds_want_syslog
bool lds_want_syslog
Indicates whether output of the stream should be sent to the syslog or not.
Definition: output.h:202
PMIX_MAXHOSTNAMELEN
#define PMIX_MAXHOSTNAMELEN
Definition: pmix_config_bottom.h:402
pmix_output_stream_t::lds_is_debugging
bool lds_is_debugging
Indicates whether the output of the stream is debugging/developer-only output or not.
Definition: output.h:187
initialized
static bool initialized
Definition: output.c:112
make_string
static int make_string(char **out, char **no_newline_string, output_desc_t *ldi, const char *format, va_list arglist)
Definition: output.c:777
pmix_output_stream_t::lds_prefix
char * lds_prefix
String prefix added to all output on the stream.
Definition: output.h:167
output_desc_t::ldi_used
bool ldi_used
Definition: output.c:61
pmix_output_open
int pmix_output_open(pmix_output_stream_t *lds)
Opens an output stream.
Definition: output.c:216
do_open
static int do_open(int output_id, pmix_output_stream_t *lds)
Definition: output.c:500
pmix_output_reopen
int pmix_output_reopen(int output_id, pmix_output_stream_t *lds)
Re-opens / redirects an output stream.
Definition: output.c:225
output_desc_t::ldi_prefix
char * ldi_prefix
Definition: output.c:69
output_desc_t::ldi_verbose_level
int ldi_verbose_level
Definition: output.c:63
pmix_output_set_verbosity
void pmix_output_set_verbosity(int output_id, int level)
Set the verbosity level for a stream.
Definition: output.c:363
pmix_output_stream_t::lds_want_file_append
bool lds_want_file_append
When pmix_output_stream_t::lds_want_file is true, this field indicates whether to append the file (if...
Definition: output.h:234
destruct
static void destruct(pmix_object_t *stream)
Definition: output.c:487
pmix_output_redirected_syslog_pri
int pmix_output_redirected_syslog_pri
Definition: output.c:107
construct
static void construct(pmix_object_t *stream)
Definition: output.c:470
PMIX_DESTRUCT
#define PMIX_DESTRUCT(object)
Destruct (finalize) an object that is not dynamically allocated.
Definition: pmix_object.h:380
output_prefix
static char * output_prefix
Definition: output.c:53
pmix_output_stream_t::lds_syslog_ident
char * lds_syslog_ident
When pmix_output_stream_t::lds_want_syslog is true, this field is examined to see what ident value sh...
Definition: output.h:152
free
free(sm_data)
pmix_output_close
void pmix_output_close(int output_id)
Close an output stream.
Definition: output.c:283
output_desc_t::ldi_syslog
bool ldi_syslog
Definition: output.c:65
pmix_output
PMIX_EXPORT void pmix_output(int output_id, const char *format,...)
Definition: output.c:321
pmix_output_finalize
void pmix_output_finalize(void)
Shut down the output stream system.
Definition: output.c:450
n
default Unknown flag passed to ADIOI_HFS_Fcntl n
Definition: ad_hfs_fcntl.c:110
output
static int output(int output_id, const char *format, va_list arglist)
Definition: output.c:854
vasprintf
#define vasprintf
Definition: pmix_config_bottom.h:432
filename
static char * filename
Definition: sync.c:26
pmix_output_stream_t::lds_want_file
bool lds_want_file
Whether to send stream output to a file or not.
Definition: output.h:226
NULL
#define NULL
Copyright (C) 2000-2004 by Etnus, LLC.
Definition: ompi_msgq_dll.c:136
free_descriptor
static void free_descriptor(int output_id)
Definition: output.c:739
pmix_tmp_directory
const char * pmix_tmp_directory(void)
Definition: pmix_environ.c:263
out
void * out
Definition: op.c:237