1
1

First cut of the output streams

This commit was SVN r360.
Этот коммит содержится в:
Jeff Squyres 2004-01-14 06:42:24 +00:00
родитель 904e4f0d58
Коммит 1140112b9b
5 изменённых файлов: 965 добавлений и 138 удалений

Просмотреть файл

@ -13,8 +13,8 @@ headers = \
argv.h \ argv.h \
cmd_line.h \ cmd_line.h \
few.h \ few.h \
lam_log.h \
malloc.h \ malloc.h \
output.h \
path.h \ path.h \
reactor.h \ reactor.h \
strncpy.h strncpy.h
@ -24,7 +24,7 @@ libutil_la_SOURCES = \
argv.c \ argv.c \
cmd_line.c \ cmd_line.c \
few.c \ few.c \
lam_log.c \ output.c \
path.c \ path.c \
reactor.c \ reactor.c \
strncpy.c strncpy.c

Просмотреть файл

@ -1,81 +0,0 @@
/*
* $HEADER$
*/
#include "lam/util/lam_log.h"
#include <stdlib.h>
#include <stdarg.h>
#define FILE_LINE_MAX 255
static char file_line[FILE_LINE_MAX + 1] = "";
void _lam_log(FILE *fd, const char *fmt, va_list ap)
{
/* Write to a file descriptor and the log file */
if (fd != NULL) {
fprintf(fd, file_line);
vfprintf(fd, fmt, ap);
fflush(fd);
}
file_line[0] = '\0';
}
void _lam_print(FILE * fd, const char *fmt, va_list ap)
{
/* Write to a file descriptor (usually stdout or stderr) */
if (fd != NULL) {
fprintf(fd, file_line);
vfprintf(fd, fmt, ap);
fflush(fd);
}
file_line[0] = '\0';
}
void _lam_set_file_line(const char *name, int line)
{
sprintf(file_line, "LAM/MPI:%s:%d: ", name, line);
}
void _lam_err(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_lam_log(stderr, fmt, ap);
va_end(ap);
}
void _lam_warn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_lam_log(stderr, fmt, ap);
va_end(ap);
}
void _lam_dbg(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_lam_log(stdout, fmt, ap);
va_end(ap);
}
void _lam_exit(int status, const char* fmt, ...)
{
va_list ap;
if (fmt) {
va_start(ap, fmt);
if (status != 0) {
_lam_log(stderr, fmt, ap);
}
else {
_lam_print(stdout, fmt, ap);
}
va_end(ap);
}
exit(status);
}

Просмотреть файл

@ -1,55 +0,0 @@
/*
* $HEADER$
*/
#ifndef LAM_LOG_H
#define LAM_LOG_H
#include <stdio.h>
#define lam_dbg(x) \
do { \
if (OPT_DBG) { \
_lam_set_file_line( __FILE__, __LINE__) ; \
_lam_dbg x ; \
} \
} while (0)
#define lam_err(x) \
do { \
_lam_set_file_line(__FILE__, __LINE__) ; \
_lam_err x ; \
} while (0)
#define lam_warn(x) \
do { \
_lam_set_file_line(__FILE__, __LINE__) ; \
_lam_warn x ; \
} while (0)
#define lam_exit(x) \
do { \
_lam_set_file_line(__FILE__, __LINE__) ; \
_lam_exit x ; \
} while (0)
/* Error condition */
void _lam_err(const char* fmt, ...);
/* Warning condition */
void _lam_warn(const char* fmt, ...);
/* Debugging message */
void _lam_dbg(const char* fmt, ...);
/* Exit with error message */
void _lam_exit(int status, const char* fmt, ...);
/* Set file and line info */
void _lam_set_file_line(const char *file, int lineno);
#endif /* LAM_LOG_H */

740
src/lam/util/output.c Обычный файл
Просмотреть файл

@ -0,0 +1,740 @@
/*
* $HEADER$
*/
#include "lam_config.h"
#include <stdio.h>
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <stdlib.h>
#include <syslog.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "lam/constants.h"
#include "lam/util/malloc.h"
#include "lam/util/output.h"
#include "lam/threads/mutex.h"
/*
* Private data
*/
int verbose_stream = -1;
int verbose_level = 0;
lam_output_stream_t verbose = {
/* debugging */
false,
/* verbose level */
0,
/* syslog */
false, 0, NULL, NULL,
/* stdout */
false,
/* stderr */
true,
/* file */
false, false, NULL
};
/*
* Private functions
*/
static void output(int output_id, char *format, va_list arglist);
static char *lam_vsnprintf(char *format, va_list arglist);
/*
* Internal data structures and helpers for the generalized output
* stream mechanism.
*/
struct output_desc_t {
bool ldi_used;
bool ldi_enabled;
int ldi_verbose_level;
bool ldi_syslog;
int ldi_syslog_priority;
char *ldi_syslog_ident;
char *ldi_prefix;
int ldi_prefix_len;
bool ldi_stdout;
bool ldi_stderr;
int ldi_fd;
char *ldi_file_suffix;
};
typedef struct output_desc_t output_desc_t;
#define LAM_OUTPUT_MAX_STREAMS 32
/*
* Local state
*/
static bool initialized = false;
static output_desc_t info[LAM_OUTPUT_MAX_STREAMS];
static char *temp_str = 0;
static int temp_str_len = 0;
static lam_mutex_t mutex;
/**
* Initializes the output stream system and opens a default
* "verbose" stream.
*
* @retval true Upon success.
* @retval false Upon failure.
*
* This should be the first function invoked in the output subsystem.
* After this call, the default "verbose" stream is open and can be
* written to via calls to lam_output_verbose() and
* lam_output_error().
*
* By definition, the default verbose stream has a handle ID of 0, and
* has a verbose level of 0.
*/
bool lam_output_init(void)
{
int i;
for (i = 0; i < LAM_OUTPUT_MAX_STREAMS; ++i) {
info[i].ldi_used = false;
info[i].ldi_enabled = false;
info[i].ldi_syslog = false;
info[i].ldi_fd = -1;
}
/* Initialize the mutex that protects the output */
lam_mutex_init(&mutex);
initialized = true;
/* Open the default verbose stream */
verbose_stream = lam_output_open(&verbose);
return true;
}
/**
* Opens output streams.
*
* @param lds A pointer to lam_output_stream_t describing what the
* characteristics of the output stream should be.
*
* This function opens an output stream and returns an integer handle.
* The caller is responsible for maintaining the handle and using it
* in successive calls to LAM_OUTPUT(), lam_output(),
* lam_output_switch(), and lam_output_close().
*
* It is safe to have multiple threads invoke this function
* simultaneously; their execution will be serialized in an
* unspecified manner.
*/
int lam_output_open(lam_output_stream_t *lds)
{
int i;
int flags;
char *filename;
/* Setup */
if (!initialized)
lam_output_init();
/* Find an available stream, or return LAM_ERROR */
THREAD_LOCK(&mutex);
for (i = 0; i < LAM_OUTPUT_MAX_STREAMS; ++i)
if (!info[i].ldi_used)
break;
if (i >= LAM_OUTPUT_MAX_STREAMS) {
THREAD_UNLOCK(&mutex);
return LAM_ERR_OUT_OF_RESOURCE;
}
/* Got a stream -- now initialize it and open relevant outputs */
info[i].ldi_used = true;
THREAD_UNLOCK(&mutex);
info[i].ldi_enabled = lds->lds_is_debugging ? (bool) LAM_ENABLE_DEBUG : true;
info[i].ldi_verbose_level = 0;
info[i].ldi_syslog = lds->lds_want_syslog;
if (lds->lds_want_syslog) {
if (NULL != lds->lds_syslog_ident) {
info[i].ldi_syslog_ident = strdup(lds->lds_syslog_ident);
openlog(lds->lds_syslog_ident, LOG_PID, LOG_USER);
} else {
info[i].ldi_syslog_ident = NULL;
openlog("lam", LOG_PID, LOG_USER);
}
info[i].ldi_syslog_priority = lds->lds_syslog_priority;
}
if (NULL != lds->lds_prefix) {
info[i].ldi_prefix = strdup(lds->lds_prefix);
info[i].ldi_prefix_len = strlen(lds->lds_prefix);
} else {
info[i].ldi_prefix = NULL;
info[i].ldi_prefix_len = 0;
}
info[i].ldi_stdout = lds->lds_want_stdout;
info[i].ldi_stderr = lds->lds_want_stderr;
info[i].ldi_fd = -1;
if (lds->lds_want_file) {
/* Setup the filename and open flags */
#if NEED_TO_IMPLEMENT_SESSION_DIRECTORY
filename = lam_get_tmpdir();
#else
filename = LAM_MALLOC(256);
strcpy(filename, "/tmp");
#endif
strcat(filename, "/lam-");
if (lds->lds_file_suffix != NULL) {
info[i].ldi_file_suffix = strdup(lds->lds_file_suffix);
strcat(filename, lds->lds_file_suffix);
} else {
info[i].ldi_file_suffix = NULL;
strcat(filename, "output.txt");
}
flags = O_CREAT | O_RDWR;
if (!lds->lds_want_file_append)
flags |= O_TRUNC;
/* Actually open the file */
info[i].ldi_fd = open(filename, flags, 0644);
if (-1 == info[i].ldi_fd) {
info[i].ldi_used = false;
return LAM_ERR_IN_ERRNO;
}
/* Make the file be close-on-exec to prevent child inheritance
problems */
fcntl(info[i].ldi_fd, F_SETFD, 1);
LAM_FREE(filename);
}
return i;
}
/**
* Enables and disables output streams.
*
* @param output_id Stream handle to switch
* @param enable Boolean indicating whether to enable the stream
* output or not.
*
* @returns The previous enable state of the stream (true == enabled,
* false == disabled).
*
* The output of a stream can be temporarily disabled by passing an
* enable value to false, and later resumed by passing an enable value
* of true. This does not close the stream -- it simply tells the
* lam_output subsystem to intercept and discard any output sent to
* the stream via LAM_OUTPUT() or lam_output() until the output is
* re-enabled.
*/
bool lam_output_switch(int output_id, bool enable)
{
bool ret = false;
/* Setup */
if (!initialized)
lam_output_init();
if (output_id >= 0 && output_id < LAM_OUTPUT_MAX_STREAMS) {
ret = info[output_id].ldi_enabled;
info[output_id].ldi_enabled = enable;
}
return ret;
}
/**
* \internal
*
* Reopens all existing output streams.
*
* This function should never be called by user applications; it is
* typically only invoked after a restart (i.e., in a new process)
* where output streams need to be re-initialized.
*/
void lam_output_reopen_all(void)
{
int i;
lam_output_stream_t lds;
for (i = 0; i < LAM_OUTPUT_MAX_STREAMS; ++i) {
/* scan till we find ldi_used == 0, which is the end-marker */
if (!info[i].ldi_used)
break;
/*
* set this to zero to ensure that lam_output_open will return this same
* index as the output stream id
*/
info[i].ldi_used = false;
lds.lds_want_syslog = info[i].ldi_syslog;
lds.lds_syslog_priority = info[i].ldi_syslog_priority;
lds.lds_syslog_ident = info[i].ldi_syslog_ident;
lds.lds_prefix = info[i].ldi_prefix;
lds.lds_want_stdout = info[i].ldi_stdout;
lds.lds_want_stderr = info[i].ldi_stderr;
lds.lds_want_file = (-1 == info[i].ldi_fd) ? false: true;
/* open all streams in append mode */
lds.lds_want_file_append = true;
lds.lds_file_suffix = info[i].ldi_file_suffix;
/*
* call lam_output_open to open the stream. The return value is
* guaranteed to be i. So we can ignore it.
*/
lam_output_open(&lds);
}
}
/**
* Close an output stream.
*
* @param output_id Handle of the stream to close.
*
* Close an output stream. No output will be sent to the stream after
* it is closed. Be aware that output handles tend to be re-used; it
* is possible that after a stream is closed, if another stream is
* opened, it will get the same handle value.
*/
void lam_output_close(int output_id)
{
int i;
output_desc_t *ldi;
/* Setup */
if (!initialized)
lam_output_init();
/* If it's valid, used, enabled, and has an open file descriptor,
close it */
if (output_id >= 0 && output_id < LAM_OUTPUT_MAX_STREAMS &&
info[output_id].ldi_used &&
info[output_id].ldi_enabled) {
ldi = &info[output_id];
if (-1 != ldi->ldi_fd)
close(ldi->ldi_fd);
ldi->ldi_used = false;
/* If we strduped a prefix, suffix, or syslog ident, free it */
if (NULL != ldi->ldi_prefix)
LAM_FREE(ldi->ldi_prefix);
ldi->ldi_prefix = NULL;
if (NULL != ldi->ldi_file_suffix)
LAM_FREE(ldi->ldi_file_suffix);
ldi->ldi_file_suffix = NULL;
if (NULL != ldi->ldi_syslog_ident)
LAM_FREE(ldi->ldi_syslog_ident);
ldi->ldi_syslog_ident = NULL;
}
/* If no one has the syslog open, we should close it */
THREAD_LOCK(&mutex);
for (i = 0; i < LAM_OUTPUT_MAX_STREAMS; ++i)
if (info[i].ldi_used && info[i].ldi_syslog)
break;
if (i >= LAM_OUTPUT_MAX_STREAMS)
closelog();
/* Somewhat of a hack to free up the temp_str */
if (NULL != temp_str) {
LAM_FREE(temp_str);
temp_str = NULL;
temp_str_len = 0;
}
THREAD_UNLOCK(&mutex);
}
/**
* Main function to send output to a stream.
*
* @param output_id Stream id returned from lam_output_open().
* @param format printf-style format string.
* @param varargs printf-style varargs list to fill the string
* specified by the format parameter.
*
* This is the main function to send output to custom streams (note
* that output to the default "verbose" stream is handled through
* lam_output_verbose() and lam_output_error()).
*
* It is never necessary to send a trailing "\n" in the strings to
* this function; some streams requires newlines, others do not --
* this function will append newlines as necessary.
*
* Verbosity levels are ignored in this function.
*/
void lam_output(int output_id, char *format, ...)
{
va_list arglist;
#if __STDC__
va_start(arglist, format);
#else
va_start(arglist);
#endif
output(output_id, format, arglist);
va_end(arglist);
}
/**
* Send output to a stream only if the passed verbosity level is high
* enough.
*
* @param output_id Stream id returned from lam_output_open().
* @param level Target verbosity level.
* @param format printf-style format string.
* @param varargs printf-style varargs list to fill the string
* specified by the format parameter.
*
* Output is only sent to the stream if the current verbosity level is
* greater than or equal to the level parameter. This mechanism can
* be used to send "information" kinds of output to user applications,
* but only when the user has asked for a high enough verbosity level.
*
* It is never necessary to send a trailing "\n" in the strings to
* this function; some streams requires newlines, others do not --
* this function will append newlines as necessary.
*
* This function is really a convenience wrapper around checking the
* current verbosity level set on the stream, and if the passed level
* is less than or equal to the stream's verbosity level, this
* function will effectively invoke lam_output to send the output to
* the stream.
*
* @see lam_output_set_verbosity()
*/
void lam_output_verbose(int output_id, int level, char *format, ...)
{
if (info[output_id].ldi_verbose_level >= level) {
va_list arglist;
#if __STDC__
va_start(arglist, format);
#else
va_start(arglist);
#endif
output(output_id, format, arglist);
va_end(arglist);
}
}
/**
* Set the verbosity level for a stream.
*
* @param output_id Stream id returned from lam_output_open().
* @param level New verbosity level
*
* This function sets the verbosity level on a given stream. It will
* be used for all future invocations of lam_output_verbose().
*/
void lam_output_set_verbosity(int output_id, int level)
{
info[output_id].ldi_verbose_level = level;
}
/**
* Shut down the output stream system.
*
* Shut down the output stream system, including the default verbose
* stream.
*/
void lam_output_finalize(void)
{
if (initialized) {
if (verbose_stream != -1)
lam_output_close(verbose_stream);
verbose_stream = -1;
}
}
/*
* Do the actual output. Take a va_list so that we can be called from
* multiple different places, even functions that took "..." as input
* arguments.
*/
static void output(int output_id, char *format, va_list arglist)
{
int len, total_len;
bool want_newline = false;
char *str;
output_desc_t *ldi;
/* Setup */
if (!initialized)
lam_output_init();
/* If it's valid, used, and enabled, output */
if (output_id >= 0 && output_id < LAM_OUTPUT_MAX_STREAMS &&
info[output_id].ldi_used &&
info[output_id].ldi_enabled) {
ldi = &info[output_id];
/* Make the formatted string */
THREAD_LOCK(&mutex);
str = lam_vsnprintf(format, arglist);
total_len = len = strlen(str);
if ('\n' != str[len - 1]) {
want_newline = true;
++total_len;
}
if (NULL != ldi->ldi_prefix)
total_len += strlen(ldi->ldi_prefix);
if (temp_str_len < total_len + want_newline) {
if (NULL != temp_str)
LAM_FREE(temp_str);
temp_str = malloc(total_len * 2);
temp_str_len = total_len * 2;
}
if (NULL != ldi->ldi_prefix) {
if (want_newline)
snprintf(temp_str, temp_str_len, "%s%s\n", ldi->ldi_prefix, str);
else
snprintf(temp_str, temp_str_len, "%s%s", ldi->ldi_prefix, str);
} else {
if (want_newline)
snprintf(temp_str, temp_str_len, "%s\n", str);
else
snprintf(temp_str, temp_str_len, "%s", str);
}
/* Syslog output */
if (ldi->ldi_syslog)
syslog(ldi->ldi_syslog_priority, str);
/* stdout output */
if (ldi->ldi_stdout) {
printf(temp_str);
fflush(stdout);
}
/* stderr output */
if (ldi->ldi_stderr) {
fprintf(stderr, temp_str);
fflush(stderr);
}
/* File output */
if (ldi->ldi_fd != -1)
write(ldi->ldi_fd, temp_str, total_len);
THREAD_UNLOCK(&mutex);
LAM_FREE(str);
}
}
/*
* lam_vsnprintf
*
* Make a good guess about how long a printf-style varags formatted
* string will be once all the % escapes are filled in. We don't
* handle every % escape here, but we handle enough, and then add a
* fudge factor in at the end. When we have that, alloc out a buffer
* and snprintf into it. The whole reason for this routine is because
* we can't count on vsnprintf to be on every system. :-( Ok, it's
* not exactly the same as vsnprintf, but it's in the same spirit, so
* it's ok to use a derrivative of the name...
*/
static char *lam_vsnprintf(char *format, va_list arglist)
{
int i, len;
char *sarg;
int iarg;
long larg;
double darg;
float farg;
/* Important: keep a copy of the original arglist because when we
traverse through the original arglist, it has internal state that
knows where it is in the list of args. At the end of this
routine, we'll need the whole list in order to call vsprintf(),
and there doesn't appear to be a way to "rewind" a va_alist.
Copy order taken from Autoconf docs
*/
va_list arglist2;
#if LAM_HAVE_VA_COPY
va_copy(arglist2, arglist);
#elif LAM_HAVE_UNDERSCORE_VA_COPY
__va_copy(arglist2, arglist);
#else
memcpy (&arglist2, &arglist, sizeof(va_list));
#endif
/* Start off with a fudge factor of 128 to handle the % escapes that
we aren't calculating here */
len = strlen(format) + 128;
for (i = 0; i < strlen(format); ++i) {
if ('%' == format[i] && i + 1 < strlen(format) && '%' != format[i + 1]) {
++i;
switch(format[i]) {
case 's':
sarg = va_arg(arglist, char*);
/* If there's an arg, get the strlen, otherwise we'll use (null) */
if (NULL != sarg)
len += strlen(sarg);
else
len += 5;
break;
case 'd':
case 'i':
iarg = va_arg(arglist, int);
/* Alloc for minus sign */
if (iarg < 0)
++len;
/* Now get the log10 */
do {
++len;
iarg /= 10;
} while (0 != iarg);
break;
case 'x':
case 'X':
iarg = va_arg(arglist, int);
/* Now get the log16 */
do {
++len;
iarg /= 16;
} while (0 != iarg);
break;
case 'f':
farg = va_arg(arglist, int);
/* Alloc for minus sign */
if (farg < 0) {
++len;
farg = -farg;
}
/* Alloc for 3 decimal places + '.' */
len += 4;
/* Now get the log10 */
do {
++len;
farg /= 10.0;
} while (0 != farg);
break;
case 'g':
darg = va_arg(arglist, int);
/* Alloc for minus sign */
if (darg < 0) {
++len;
darg = -darg;
}
/* Alloc for 3 decimal places + '.' */
len += 4;
/* Now get the log10 */
do {
++len;
darg /= 10.0;
} while (0 != darg);
break;
case 'l':
/* Get %ld %lx %lX %lf */
if (i + 1 < strlen(format)) {
++i;
switch(format[i]) {
case 'x':
case 'X':
larg = va_arg(arglist, int);
/* Now get the log16 */
do {
++len;
larg /= 16;
} while (0 != larg);
break;
case 'f':
darg = va_arg(arglist, int);
/* Alloc for minus sign */
if (darg < 0) {
++len;
darg = -darg;
}
/* Alloc for 3 decimal places + '.' */
len += 4;
/* Now get the log10 */
do {
++len;
darg /= 10.0;
} while (0 != darg);
break;
case 'd':
default:
larg = va_arg(arglist, int);
/* Now get the log10 */
do {
++len;
larg /= 10;
} while (0 != larg);
break;
}
}
default:
break;
}
}
}
/* Wasn't that simple? Now malloc out a string and do the final
formatting into that string. */
sarg = LAM_MALLOC(len);
vsprintf(sarg, format, arglist2);
/* Return the new string */
return sarg;
}

223
src/lam/util/output.h Обычный файл
Просмотреть файл

@ -0,0 +1,223 @@
/*
* $HEADER$
*/
/** @file
* LAM output stream facility.
*
* The LAM output stream facility is used to send output from the LAM
* libraries to output devices. It is meant to fully replace all
* forms of printf() (and friends). Output streams are opened via the
* lam_output_open() function call, and then sent output via
* lam_output_verbose(), LAM_OUTPUT(), and lam_output(). Streams are
* closed with lam_output_close().
*
* Streams can multiplex output to several kinds of outputs (one of
* each):
*
* - the syslog
* - standard output
* - standard error
* - file
*
* Which outputs to use are specified during lam_output_open().
*
* lam_output_open() returns an integer handle that is used in
* successive calls to LAM_OUTPUT() and lam_output() to send output to
* the stream.
*
* The default "verbose" stream is opened after invoking
* lam_output_init() (and closed after invoking
* lam_output_finalize()). This stream outputs to stderr only, and
* has a stream handle ID of 0.
*
* It is erroneous to have one thread close a stream and have another
* try to write to it. Multiple threads writing to a single stream
* will be serialized in an unspecified order.
*/
#ifndef LAM_OUTPUT_H_
#define LAM_OUTPUT_H_
#include "lam_config.h"
#if __STDC__
#include <stdarg.h>
#else
#ifdef __cplusplus
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#endif /* __STDC__ */
/**
* \class lam_output_stream_t
*
* Structure used to request the opening of a LAM output stream. A
* pointer to this structure is passed to lam_output_open() to tell
* the lam_output subsystem where to send output for a given stream.
* It is valid to specify multiple destinations of output for a stream
* -- output streams can be multiplexed to multiple different
* destinations through the lam_output facility.
*
* Note that all strings in this struct are cached on the stream by
* value; there is no need to keep them allocated after the return
* from lam_output_open().
*
* @see output.h
*/
struct lam_output_stream_t {
/**
* Indicates whether the output of the stream is
* debugging/developer-only output or not.
*
* This field should be "true" if the output is for debugging
* purposes only. In that case, the output will never be sent to
* the stream unless LAM was configured with --enable-debug.
*/
bool lds_is_debugging;
/**
* Indicate the starting verbosity level of the stream.
*
* Verbose levels are a convenience mechanisms, and are only
* consulted when output is sent to a stream through the
* lam_output_verbose() function. Verbose levels are ignored in
* LAM_OUTPUT() and lam_output().
*
* Valid verbose levels typically start at 0 (meaning "minimal
* information"). Higher verbosity levels generally indicate that
* more output and diagnostics should be displayed.
*/
int lda_verbose_level;
/**
* Indicates whether output of the stream should be sent to the
* syslog or not.
*
* If this field is true, output from this stream is sent to the
* syslog, and the following fields are also examined:
*
* - lds_syslog_priority
* - lds_syslog_ident
* - lds_prefix
*
* If this field is false, the above three fields are ignored.
*/
bool lds_want_syslog;
/**
* When lam_output_stream_t::lds_want_syslog is true, this field is
* examined to see what priority output from the stream should be
* sent to the syslog.
*
* This value should be set as per the syslog(3) man page. It is
* typically the OR value of "facilty" and "level" values described
* in the man page.
*/
int lds_syslog_priority;
/**
* When lam_output_stream_t::lds_want_syslog is true, this field is
* examined to see what ident value should be passed to openlog(3).
*
* If a NULL value is given, the string "lam" is used.
*/
char *lds_syslog_ident;
/**
* String prefix added to all output on the stream.
*
* When this field is non-NULL, it is prefixed to all lines of
* output on the stream. When this field is NULL, no prefix is
* added to each line of output in the stream.
*/
char *lds_prefix;
/**
* Whether to send stream output to stdout or not.
*
* If this field is true, stream output is sent to stdout.
*/
bool lds_want_stdout;
/**
* Whether to send stream output to stderr or not.
*
* If this field is true, stream output is sent to stderr.
*/
bool lds_want_stderr;
/**
* Whether to send stream output to a file or not.
*
* When this field is true, stream output is sent to a file, and the
* following fields are also examined:
*
* - lds_want_file_append
* - lda_file_suffix
*/
bool lds_want_file;
/**
* When lam_output_stream_t::lds_want_file is true, this field
* indicates whether to append the file (if it exists) or overwrite
* it.
*
* If false, the file is opened with the O_TRUNC flag.
*/
bool lds_want_file_append;
/**
* When lam_output_stream_t::lds_want_file is true, this field
* indicates the string suffix to add to the filename.
*
* The output file will be in the LAM session directory and have a
* LAM-generated prefix (generally "$sessiondir/lam-"). The suffix
* is intended to give stream users a chance to write their output
* into unique files. If this field is NULL, the suffix
* "output.txt" is used.
*/
char *lds_file_suffix;
};
typedef struct lam_output_stream_t lam_output_stream_t;
#ifdef __cplusplus
extern "C" {
#endif
bool lam_output_init(void);
void lam_output_finalize(void);
int lam_output_open(lam_output_stream_t *lds);
bool lam_output_switch(int output_id, bool enable);
void lam_output_reopen_all(void);
void lam_output_close(int output_id);
void lam_output(int output_id, char *format, ...);
void lam_output_verbose(int output_id, int verbose_level, char *format, ...);
void lam_output_set_verbosity(int output_id, int level);
#if LAM_ENABLE_DEBUG
/**
* Main macro for use in sending debugging output to output streams;
* will be "compiled out" when LAM is configured without
* --enable-debug.
*
* @see lam_output()
*/
#define LAM_OUTPUT(a) lam_output a
#else
/**
* Main macro for use in sending debugging output to output streams;
* will be "compiled out" when LAM is configured without
* --enable-debug.
*
* @see lam_output()
*/
#define LAM_OUTPUT(a)
#endif
#ifdef __cplusplus
}
#endif
#endif /* LAM_OUTPUT_H_ */