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) 2007-2011 Cisco Systems, Inc.  All rights reserved.
13  * Copyright (c) 2010      Oracle and/or its affiliates.  All rights reserved.
14  * Copyright (c) 2015-2020 Intel, Inc.  All rights reserved.
15  * Copyright (c) 2016      Research Organization for Information Science
16  *                         and Technology (RIST). All rights reserved.
17  * $COPYRIGHT$
18  *
19  * Additional copyrights may follow
20  *
21  * $HEADER$
22  */
23 
24 /** @file
25  * PMIX output stream facility.
26  *
27  * The PMIX output stream facility is used to send output from the PMIX
28  * libraries to output devices.  It is meant to fully replace all
29  * forms of printf() (and friends).  Output streams are opened via the
30  * pmix_output_open() function call, and then sent output via
31  * pmix_output_verbose(), PMIX_OUTPUT(), and pmix_output().  Streams are
32  * closed with pmix_output_close().
33  *
34  * Streams can multiplex output to several kinds of outputs (one of
35  * each):
36  *
37  * - the syslog (if available)
38  * - standard output
39  * - standard error
40  * - file
41  *
42  * Which outputs to use are specified during pmix_output_open().
43  *
44  * WARNING: When using "file" as an output destination, be aware that
45  * the file may not exist until the session directory for the process
46  * exists.  This is at least part of the way through MPI_INIT (for
47  * example).  Most MCA components and internals of PMIx won't be
48  * affected by this, but some RTE / startup aspects of PMIx will
49  * not be able to write to a file for output.  See pmix_output() for
50  * details on what happens in these cases.
51  *
52  * pmix_output_open() returns an integer handle that is used in
53  * successive calls to PMIX_OUTPUT() and pmix_output() to send output to
54  * the stream.
55  *
56  * The default "verbose" stream is opened after invoking
57  * pmix_output_init() (and closed after invoking
58  * pmix_output_finalize()).  This stream outputs to stderr only, and
59  * has a stream handle ID of 0.
60  *
61  * It is erroneous to have one thread close a stream and have another
62  * try to write to it.  Multiple threads writing to a single stream
63  * will be serialized in an unspecified order.
64  */
65 
66 #ifndef PMIX_OUTPUT_H_
67 #define PMIX_OUTPUT_H_
68 
69 #include "src/include/pmix_config.h"
70 
71 
72 #ifdef HAVE_STDARG_H
73 #include <stdarg.h>
74 #endif
75 
76 #include "src/class/pmix_object.h"
77 
78 BEGIN_C_DECLS
79 
80 /* There are systems where all output needs to be redirected to syslog
81  * and away from stdout/stderr or files - e.g., embedded systems whose
82  * sole file system is in flash. To support such systems, we provide
83  * the following environmental variables that support redirecting -all-
84  * output (both from pmix_output and stdout/stderr of processes) to
85  * syslog:
86  *
87  * PMIX_OUTPUT_REDIRECT - set to "syslog" to redirect to syslog. Other
88  *                        options may someday be supported
89  * PMIX_OUTPUT_SYSLOG_PRI - set to "info", "error", or "warn" to have
90  *                        output sent to syslog at that priority
91  * PMIX_OUTPUT_SYSLOG_IDENT - a string identifier for the log
92  *
93  * We also define two global variables that notify all other
94  * layers that output is being redirected to syslog at the given
95  * priority. These are used, for example, by the IO forwarding
96  * subsystem to tell it to dump any collected output directly to
97  * syslog instead of forwarding it to another location.
98  */
99 extern bool pmix_output_redirected_to_syslog;
100 extern int pmix_output_redirected_syslog_pri;
101 
102 /**
103  * \class pmix_output_stream_t
104  *
105  * Structure used to request the opening of a PMIX output stream.  A
106  * pointer to this structure is passed to pmix_output_open() to tell
107  * the pmix_output subsystem where to send output for a given stream.
108  * It is valid to specify multiple destinations of output for a stream
109  * -- output streams can be multiplexed to multiple different
110  * destinations through the pmix_output facility.
111  *
112  * Note that all strings in this struct are cached on the stream by
113  * value; there is no need to keep them allocated after the return
114  * from pmix_output_open().
115  */
116 struct pmix_output_stream_t {
117     /** Class parent */
118     pmix_object_t super;
119 
120     /**
121      * Indicate the starting verbosity level of the stream.
122      *
123      * Verbose levels are a convenience mechanisms, and are only
124      * consulted when output is sent to a stream through the
125      * pmix_output_verbose() function.  Verbose levels are ignored in
126      * PMIX_OUTPUT() and pmix_output().
127      *
128      * Valid verbose levels typically start at 0 (meaning "minimal
129      * information").  Higher verbosity levels generally indicate that
130      * more output and diagnostics should be displayed.
131      */
132     int lds_verbose_level;
133 
134     /**
135      * When pmix_output_stream_t::lds_want_syslog is true, this field is
136      * examined to see what priority output from the stream should be
137      * sent to the syslog.
138      *
139      * This value should be set as per the syslog(3) man page.  It is
140      * typically the OR value of "facilty" and "level" values described
141      * in the man page.
142      */
143     int lds_syslog_priority;
144     /**
145      * When pmix_output_stream_t::lds_want_syslog is true, this field is
146      * examined to see what ident value should be passed to openlog(3).
147      *
148      * If a NULL value is given, the string "pmix" is used.
149      */
150 #if !defined(__WINDOWS__)
151     char *lds_syslog_ident;
152 #elif !defined(_MSC_VER)
153     char *lds_syslog_ident;
154 #else
155     HANDLE lds_syslog_ident;
156 #endif  /* !defined(__WINDOWS__) */
157 
158     /**
159      * String prefix added to all output on the stream.
160      *
161      * When this field is non-NULL, it is prefixed to all lines of
162      * output on the stream.  When this field is NULL, no prefix is
163      * added to each line of output in the stream. The prefix is copied
164      * to an internal structure in the call to pmix_output_open()!
165      */
166     char *lds_prefix;
167 
168     /**
169      * String suffix added to all output on the stream.
170      *
171      * When this field is non-NULL, it is appended to all lines of
172      * output on the stream.  When this field is NULL, no suffix is
173      * added to each line of output in the stream. The suffix is copied
174      * to an internal structure in the call to pmix_output_open()!
175      */
176     char *lds_suffix;
177 
178     /**
179      * Indicates whether the output of the stream is
180      * debugging/developer-only output or not.
181      *
182      * This field should be "true" if the output is for debugging
183      * purposes only.  In that case, the output will never be sent to
184      * the stream unless PMIX was configured with --enable-debug.
185      */
186     bool lds_is_debugging;
187 
188     /**
189      * Indicates whether output of the stream should be sent to the
190      * syslog or not.
191      *
192      * If this field is true, output from this stream is sent to the
193      * syslog, and the following fields are also examined:
194      *
195      * - lds_syslog_priority
196      * - lds_syslog_ident
197      * - lds_prefix
198      *
199      * If this field is false, the above three fields are ignored.
200      */
201     bool lds_want_syslog;
202 
203     /**
204      * Whether to send stream output to stdout or not.
205      *
206      * If this field is true, stream output is sent to stdout.
207      */
208     bool lds_want_stdout;
209     /**
210      * Whether to send stream output to stderr or not.
211      *
212      * If this field is true, stream output is sent to stderr.
213      */
214     bool lds_want_stderr;
215 
216     /**
217      * Whether to send stream output to a file or not.
218      *
219      * When this field is true, stream output is sent to a file, and the
220      * following fields are also examined:
221      *
222      * - lds_want_file_append
223      * - lda_file_suffix
224      */
225     bool lds_want_file;
226     /**
227      * When pmix_output_stream_t::lds_want_file is true, this field
228      * indicates whether to append the file (if it exists) or overwrite
229      * it.
230      *
231      * If false, the file is opened with the O_TRUNC flag.
232      */
233     bool lds_want_file_append;
234     /**
235      * When pmix_output_stream_t::lds_want_file is true, this field
236      * indicates the string suffix to add to the filename.
237      *
238      * The output file will be in the directory and begin with the
239      * prefix set by pmix_output_set_output_file_info() (e.g.,
240      * "$dir/$prefix$suffix").  If this field is NULL and
241      * lds_want_file is true, then the suffix "output.txt" is used.
242      *
243      * Note that it is possible that the output directory may not
244      * exist when pmix_output_open() is invoked.  See pmix_output()
245      * for details on what happens in this situation.
246      */
247     char *lds_file_suffix;
248 
249 };
250 
251 /**
252  * Convenience typedef
253  */
254 typedef struct pmix_output_stream_t pmix_output_stream_t;
255 
256 /**
257  * Initializes the output stream system and opens a default
258  * "verbose" stream.
259  *
260  * @retval true Upon success.
261  * @retval false Upon failure.
262  *
263  * This should be the first function invoked in the output
264  * subsystem.  After this call, the default "verbose" stream is open
265  * and can be written to via calls to pmix_output_verbose() and
266  * pmix_output_error().
267  *
268  * By definition, the default verbose stream has a handle ID of 0,
269  * and has a verbose level of 0.
270  */
271 PMIX_EXPORT bool pmix_output_init(void);
272 
273 /**
274  * Shut down the output stream system.
275  *
276  * Shut down the output stream system, including the default verbose
277  * stream.
278  */
279 PMIX_EXPORT void pmix_output_finalize(void);
280 
281 /**
282  * Opens an output stream.
283  *
284  * @param lds A pointer to pmix_output_stream_t describing what the
285  * characteristics of the output stream should be.
286  *
287  * This function opens an output stream and returns an integer
288  * handle.  The caller is responsible for maintaining the handle and
289  * using it in successive calls to PMIX_OUTPUT(), pmix_output(),
290  * pmix_output_switch(), and pmix_output_close().
291  *
292  * If lds is NULL, the default descriptions will be used, meaning
293  * that output will only be sent to stderr.
294  *
295  * It is safe to have multiple threads invoke this function
296  * simultaneously; their execution will be serialized in an
297  * unspecified manner.
298  *
299  * Be sure to see pmix_output() for a description of what happens
300  * when open_open() / pmix_output() is directed to send output to a
301  * file but the process session directory does not yet exist.
302  */
303 PMIX_EXPORT int pmix_output_open(pmix_output_stream_t *lds);
304 
305 /**
306  * Re-opens / redirects an output stream.
307  *
308  * @param output_id Stream handle to reopen
309  * @param lds A pointer to pmix_output_stream_t describing what the
310  * characteristics of the reopened output stream should be.
311  *
312  * This function redirects an existing stream into a new [set of]
313  * location[s], as specified by the lds parameter.  If the output_id
314  * passed is invalid, this call is effectively the same as opening a
315  * new stream with a specific stream handle.
316  */
317 PMIX_EXPORT int pmix_output_reopen(int output_id, pmix_output_stream_t *lds);
318 
319 /**
320  * Enables and disables output streams.
321  *
322  * @param output_id Stream handle to switch
323  * @param enable Boolean indicating whether to enable the stream
324  * output or not.
325  *
326  * @returns The previous enable state of the stream (true == enabled,
327  * false == disabled).
328  *
329  * The output of a stream can be temporarily disabled by passing an
330  * enable value to false, and later resumed by passing an enable
331  * value of true.  This does not close the stream -- it simply tells
332  * the pmix_output subsystem to intercept and discard any output sent
333  * to the stream via PMIX_OUTPUT() or pmix_output() until the output
334  * is re-enabled.
335  */
336 PMIX_EXPORT bool pmix_output_switch(int output_id, bool enable);
337 
338 /**
339  * \internal
340  *
341  * Reopens all existing output streams.
342  *
343  * This function should never be called by user applications; it is
344  * typically only invoked after a restart (i.e., in a new process)
345  * where output streams need to be re-initialized.
346  */
347 PMIX_EXPORT void pmix_output_reopen_all(void);
348 
349 /**
350  * Close an output stream.
351  *
352  * @param output_id Handle of the stream to close.
353  *
354  * Close an output stream.  No output will be sent to the stream
355  * after it is closed.  Be aware that output handles tend to be
356  * re-used; it is possible that after a stream is closed, if another
357  * stream is opened, it will get the same handle value.
358  */
359 PMIX_EXPORT void pmix_output_close(int output_id);
360 
361 /**
362  * Main function to send output to a stream.
363  *
364  * @param output_id Stream id returned from pmix_output_open().
365  * @param format printf-style format string.
366  * @param varargs printf-style varargs list to fill the string
367  * specified by the format parameter.
368  *
369  * This is the main function to send output to custom streams (note
370  * that output to the default "verbose" stream is handled through
371  * pmix_output_verbose() and pmix_output_error()).
372  *
373  * It is never necessary to send a trailing "\n" in the strings to
374  * this function; some streams requires newlines, others do not --
375  * this function will append newlines as necessary.
376  *
377  * Verbosity levels are ignored in this function.
378  *
379  * Note that for output streams that are directed to files, the
380  * files are stored under the process' session directory.  If the
381  * session directory does not exist when pmix_output() is invoked,
382  * the output will be discarded!  Once the session directory is
383  * created, pmix_output() will automatically create the file and
384  * writing to it.
385  */
386 PMIX_EXPORT void pmix_output(int output_id, const char *format, ...) __pmix_attribute_format__(__printf__, 2, 3);
387 
388 /**
389  * Send output to a stream only if the passed verbosity level is
390  * high enough.
391  *
392  * @param output_id Stream id returned from pmix_output_open().
393  * @param level Target verbosity level.
394  * @param format printf-style format string.
395  * @param varargs printf-style varargs list to fill the string
396  * specified by the format parameter.
397  *
398  * Output is only sent to the stream if the current verbosity level
399  * is greater than or equal to the level parameter.  This mechanism
400  * can be used to send "information" kinds of output to user
401  * applications, but only when the user has asked for a high enough
402  * verbosity level.
403  *
404  * It is never necessary to send a trailing "\n" in the strings to
405  * this function; some streams requires newlines, others do not --
406  * this function will append newlines as necessary.
407  *
408  * This function is really a convenience wrapper around checking the
409  * current verbosity level set on the stream, and if the passed
410  * level is less than or equal to the stream's verbosity level, this
411  * function will effectively invoke pmix_output to send the output to
412  * the stream.
413  *
414  * @see pmix_output_set_verbosity()
415  */
416 #define pmix_output_verbose(verbose_level, output_id, ...) \
417     if (pmix_output_check_verbosity(verbose_level, output_id)) { \
418         pmix_output(output_id, __VA_ARGS__); \
419     }
420 
421 PMIX_EXPORT bool pmix_output_check_verbosity(int verbose_level, int output_id);
422 
423 PMIX_EXPORT void pmix_output_vverbose(int verbose_level, int output_id,
424                                       const char *format, va_list ap) __pmix_attribute_format__(__printf__, 3, 0);
425 
426 /**
427  * Set the verbosity level for a stream.
428  *
429  * @param output_id Stream id returned from pmix_output_open().
430  * @param level New verbosity level
431  *
432  * This function sets the verbosity level on a given stream.  It
433  * will be used for all future invocations of pmix_output_verbose().
434  */
435 PMIX_EXPORT void pmix_output_set_verbosity(int output_id, int level);
436 
437 /**
438  * Get the verbosity level for a stream
439  *
440  * @param output_id Stream id returned from pmix_output_open()
441  * @returns Verbosity of stream
442  */
443 PMIX_EXPORT int pmix_output_get_verbosity(int output_id);
444 
445 /**
446  * Set characteristics for output files.
447  *
448  * @param dir Directory where output files will go
449  * @param olddir If non-NULL, the directory where output files
450  * were previously opened
451  * @param prefix Prefix of files in the output directory
452  * @param oldprefix If non-NULL, the old prefix
453  *
454  * This function controls the final filename used for all new
455  * output streams that request output files.  Specifically, when
456  * pmix_output_stream_t::lds_want_file is true, the output
457  * filename will be of the form $dir/$prefix$suffix.
458  *
459  * The default value for the output directory is whatever is
460  * specified in the TMPDIR environment variable if it exists, or
461  * $HOME if it does not.  The default value for the prefix is
462  * "output-pid<pid>-" (where "<pid>" is replaced by the PID of the
463  * current process).
464  *
465  * If dir or prefix are NULL, new values are not set.  The strings
466  * represented by dir and prefix are copied into internal storage;
467  * it is safe to pass string constants or free() these values
468  * after pmix_output_set_output_file_info() returns.
469  *
470  * If olddir or oldprefix are not NULL, copies of the old
471  * directory and prefix (respectively) are returned in these
472  * parameters.  The caller is responsible for calling (free) on
473  * these values.  This allows one to get the old values, output an
474  * output file in a specific directory and/or with a specific
475  * prefix, and then restore the old values.
476  *
477  * Note that this function only affects the creation of \em new
478  * streams -- streams that have already started writing to output
479  * files are not affected (i.e., their output files are not moved
480  * to the new directory).  More specifically, the pmix_output
481  * system only opens/creates output files lazily -- so calling
482  * this function affects both new streams \em and any stream that
483  * was previously opened but had not yet output anything.
484  */
485 PMIX_EXPORT void pmix_output_set_output_file_info(const char *dir,
486                                                   const char *prefix,
487                                                   char **olddir,
488                                                   char **oldprefix);
489 
490 /**
491  * Same as pmix_output_verbose(), but pointer to buffer and size.
492  */
493 PMIX_EXPORT void pmix_output_hexdump(int verbose_level, int output_id,
494                                      void *ptr, int buflen);
495 
496 #if PMIX_ENABLE_DEBUG
497     /**
498      * Main macro for use in sending debugging output to output streams;
499      * will be "compiled out" when PMIX is configured without
500      * --enable-debug.
501      *
502      * @see pmix_output()
503      */
504 #define PMIX_OUTPUT(a) pmix_output a
505 
506     /**
507      * Macro for use in sending debugging output to the output
508      * streams.  Will be "compiled out" when PMIX is configured
509      * without --enable-debug.
510      *
511      * @see pmix_output_verbose()
512      */
513 #define PMIX_OUTPUT_VERBOSE(a) pmix_output_verbose a
514 #else
515     /**
516      * Main macro for use in sending debugging output to output streams;
517      * will be "compiled out" when PMIX is configured without
518      * --enable-debug.
519      *
520      * @see pmix_output()
521      */
522 #define PMIX_OUTPUT(a)
523 
524     /**
525      * Macro for use in sending debugging output to the output
526      * streams.  Will be "compiled out" when PMIX is configured
527      * without --enable-debug.
528      *
529      * @see pmix_output_verbose()
530      */
531 #define PMIX_OUTPUT_VERBOSE(a)
532 #endif
533 
534 /**
535  * Declare the class of this type.  Note that the constructor for
536  * this class is for convenience only -- it is \em not necessary
537  * to be invoked.  If the constructor it used, it sets all values
538  * in the struct to be false / 0 (i.e., turning off all output).
539  * The intended usage is to invoke the constructor and then enable
540  * the output fields that you want.
541  */
542 PMIX_CLASS_DECLARATION(pmix_output_stream_t);
543 
544 END_C_DECLS
545 
546 #endif /* PMIX_OUTPUT_H_ */
547