2004-01-14 09:42:24 +03:00
|
|
|
/*
|
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
2004-06-07 19:33:53 +04:00
|
|
|
#include "ompi_config.h"
|
2004-01-14 09:42:24 +03:00
|
|
|
|
|
|
|
#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>
|
|
|
|
|
2004-03-19 00:35:28 +03:00
|
|
|
#include "include/constants.h"
|
2004-03-17 21:45:16 +03:00
|
|
|
#include "util/output.h"
|
|
|
|
#include "threads/mutex.h"
|
2004-01-14 09:42:24 +03:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Private data
|
|
|
|
*/
|
2004-01-21 02:20:59 +03:00
|
|
|
static int verbose_stream = -1;
|
2004-06-07 19:33:53 +04:00
|
|
|
static ompi_output_stream_t verbose = {
|
2004-01-14 09:42:24 +03:00
|
|
|
/* debugging */
|
|
|
|
false,
|
|
|
|
/* verbose level */
|
|
|
|
0,
|
|
|
|
/* syslog */
|
|
|
|
false, 0, NULL, NULL,
|
|
|
|
/* stdout */
|
|
|
|
false,
|
|
|
|
/* stderr */
|
|
|
|
true,
|
|
|
|
/* file */
|
|
|
|
false, false, NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Private functions
|
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
static int do_open(int output_id, ompi_output_stream_t *lds);
|
2004-01-16 04:33:43 +03:00
|
|
|
static void free_descriptor(int output_id);
|
2004-01-14 09:42:24 +03:00
|
|
|
static void output(int output_id, char *format, va_list arglist);
|
2004-06-07 19:33:53 +04:00
|
|
|
static char *ompi_vsnprintf(char *format, va_list arglist);
|
2004-01-14 09:42:24 +03:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
2004-06-07 19:33:53 +04:00
|
|
|
#define OMPI_OUTPUT_MAX_STREAMS 32
|
2004-01-14 09:42:24 +03:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Local state
|
|
|
|
*/
|
|
|
|
static bool initialized = false;
|
2004-06-07 19:33:53 +04:00
|
|
|
static output_desc_t info[OMPI_OUTPUT_MAX_STREAMS];
|
2004-01-14 09:42:24 +03:00
|
|
|
static char *temp_str = 0;
|
|
|
|
static int temp_str_len = 0;
|
2004-06-07 19:33:53 +04:00
|
|
|
static ompi_mutex_t mutex;
|
2004-01-14 09:42:24 +03:00
|
|
|
|
|
|
|
|
2004-03-27 05:48:04 +03:00
|
|
|
/*
|
|
|
|
* Setup the output stream infrastructure
|
2004-01-14 09:42:24 +03:00
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
bool ompi_output_init(void)
|
2004-01-14 09:42:24 +03:00
|
|
|
{
|
|
|
|
int i;
|
2004-06-07 19:33:53 +04:00
|
|
|
for (i = 0; i < OMPI_OUTPUT_MAX_STREAMS; ++i) {
|
2004-01-14 09:42:24 +03:00
|
|
|
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 */
|
|
|
|
|
2004-06-07 19:33:53 +04:00
|
|
|
OBJ_CONSTRUCT(&mutex, ompi_mutex_t);
|
2004-01-14 09:42:24 +03:00
|
|
|
initialized = true;
|
|
|
|
|
|
|
|
/* Open the default verbose stream */
|
|
|
|
|
2004-06-07 19:33:53 +04:00
|
|
|
verbose_stream = ompi_output_open(&verbose);
|
2004-01-14 09:42:24 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-27 05:48:04 +03:00
|
|
|
/*
|
|
|
|
* Open a stream
|
2004-01-14 09:42:24 +03:00
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
int ompi_output_open(ompi_output_stream_t *lds)
|
2004-01-14 09:42:24 +03:00
|
|
|
{
|
2004-01-16 04:33:43 +03:00
|
|
|
return do_open(-1, lds);
|
|
|
|
}
|
2004-01-14 09:42:24 +03:00
|
|
|
|
|
|
|
|
2004-03-27 05:48:04 +03:00
|
|
|
/*
|
|
|
|
* Reset the parameters on a stream
|
2004-01-16 04:33:43 +03:00
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
int ompi_output_reopen(int output_id, ompi_output_stream_t *lds)
|
2004-01-16 04:33:43 +03:00
|
|
|
{
|
|
|
|
return do_open(output_id, lds);
|
2004-01-14 09:42:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-27 05:48:04 +03:00
|
|
|
/*
|
|
|
|
* Enable and disable outptu streams
|
2004-01-14 09:42:24 +03:00
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
bool ompi_output_switch(int output_id, bool enable)
|
2004-01-14 09:42:24 +03:00
|
|
|
{
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
/* Setup */
|
|
|
|
|
|
|
|
if (!initialized)
|
2004-06-07 19:33:53 +04:00
|
|
|
ompi_output_init();
|
2004-01-14 09:42:24 +03:00
|
|
|
|
2004-06-07 19:33:53 +04:00
|
|
|
if (output_id >= 0 && output_id < OMPI_OUTPUT_MAX_STREAMS) {
|
2004-01-14 09:42:24 +03:00
|
|
|
ret = info[output_id].ldi_enabled;
|
|
|
|
info[output_id].ldi_enabled = enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-27 05:48:04 +03:00
|
|
|
/*
|
|
|
|
* Reopen all the streams; used during checkpoint/restart.
|
2004-01-14 09:42:24 +03:00
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
void ompi_output_reopen_all(void)
|
2004-01-14 09:42:24 +03:00
|
|
|
{
|
|
|
|
int i;
|
2004-06-07 19:33:53 +04:00
|
|
|
ompi_output_stream_t lds;
|
2004-01-14 09:42:24 +03:00
|
|
|
|
2004-06-07 19:33:53 +04:00
|
|
|
for (i = 0; i < OMPI_OUTPUT_MAX_STREAMS; ++i) {
|
2004-01-14 09:42:24 +03:00
|
|
|
|
|
|
|
/* scan till we find ldi_used == 0, which is the end-marker */
|
|
|
|
if (!info[i].ldi_used)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
2004-06-07 19:33:53 +04:00
|
|
|
* set this to zero to ensure that ompi_output_open will return this same
|
2004-01-14 09:42:24 +03:00
|
|
|
* 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;
|
|
|
|
|
|
|
|
/*
|
2004-06-07 19:33:53 +04:00
|
|
|
* call ompi_output_open to open the stream. The return value is
|
2004-01-14 09:42:24 +03:00
|
|
|
* guaranteed to be i. So we can ignore it.
|
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
ompi_output_open(&lds);
|
2004-01-14 09:42:24 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-27 05:48:04 +03:00
|
|
|
/*
|
|
|
|
* Close a stream
|
2004-01-14 09:42:24 +03:00
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
void ompi_output_close(int output_id)
|
2004-01-14 09:42:24 +03:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Setup */
|
|
|
|
|
|
|
|
if (!initialized)
|
2004-06-07 19:33:53 +04:00
|
|
|
ompi_output_init();
|
2004-01-14 09:42:24 +03:00
|
|
|
|
|
|
|
/* If it's valid, used, enabled, and has an open file descriptor,
|
2004-01-16 04:33:43 +03:00
|
|
|
free the resources associated with the descriptor */
|
2004-01-14 09:42:24 +03:00
|
|
|
|
2004-06-07 19:33:53 +04:00
|
|
|
if (output_id >= 0 && output_id < OMPI_OUTPUT_MAX_STREAMS &&
|
2004-01-14 09:42:24 +03:00
|
|
|
info[output_id].ldi_used &&
|
|
|
|
info[output_id].ldi_enabled) {
|
2004-01-16 04:33:43 +03:00
|
|
|
free_descriptor(output_id);
|
|
|
|
}
|
2004-01-14 09:42:24 +03:00
|
|
|
|
|
|
|
/* If no one has the syslog open, we should close it */
|
|
|
|
|
2004-06-25 01:39:08 +04:00
|
|
|
OMPI_THREAD_LOCK(&mutex);
|
2004-06-07 19:33:53 +04:00
|
|
|
for (i = 0; i < OMPI_OUTPUT_MAX_STREAMS; ++i)
|
2004-01-14 09:42:24 +03:00
|
|
|
if (info[i].ldi_used && info[i].ldi_syslog)
|
|
|
|
break;
|
2004-06-07 19:33:53 +04:00
|
|
|
if (i >= OMPI_OUTPUT_MAX_STREAMS)
|
2004-01-14 09:42:24 +03:00
|
|
|
closelog();
|
|
|
|
|
|
|
|
/* Somewhat of a hack to free up the temp_str */
|
|
|
|
|
|
|
|
if (NULL != temp_str) {
|
2004-02-10 03:09:36 +03:00
|
|
|
free(temp_str);
|
2004-01-14 09:42:24 +03:00
|
|
|
temp_str = NULL;
|
|
|
|
temp_str_len = 0;
|
|
|
|
}
|
2004-06-25 01:39:08 +04:00
|
|
|
OMPI_THREAD_UNLOCK(&mutex);
|
2004-01-14 09:42:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-27 05:48:04 +03:00
|
|
|
/*
|
|
|
|
* Main function to send output to a stream
|
2004-01-14 09:42:24 +03:00
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
void ompi_output(int output_id, char *format, ...)
|
2004-01-14 09:42:24 +03:00
|
|
|
{
|
|
|
|
va_list arglist;
|
|
|
|
#if __STDC__
|
|
|
|
va_start(arglist, format);
|
|
|
|
#else
|
|
|
|
va_start(arglist);
|
|
|
|
#endif
|
|
|
|
output(output_id, format, arglist);
|
|
|
|
va_end(arglist);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-27 05:48:04 +03:00
|
|
|
/*
|
|
|
|
* Send a message to a stream if the verbose level is high enough
|
2004-01-14 09:42:24 +03:00
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
void ompi_output_verbose(int output_id, int level, char *format, ...)
|
2004-01-14 09:42:24 +03:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-27 05:48:04 +03:00
|
|
|
/*
|
|
|
|
* Set the verbosity level of a stream
|
2004-01-14 09:42:24 +03:00
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
void ompi_output_set_verbosity(int output_id, int level)
|
2004-01-14 09:42:24 +03:00
|
|
|
{
|
|
|
|
info[output_id].ldi_verbose_level = level;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-27 05:48:04 +03:00
|
|
|
/*
|
|
|
|
* Shut down the output stream system
|
2004-01-14 09:42:24 +03:00
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
void ompi_output_finalize(void)
|
2004-01-14 09:42:24 +03:00
|
|
|
{
|
|
|
|
if (initialized) {
|
|
|
|
if (verbose_stream != -1)
|
2004-06-07 19:33:53 +04:00
|
|
|
ompi_output_close(verbose_stream);
|
2004-01-14 09:42:24 +03:00
|
|
|
verbose_stream = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-03-27 05:48:04 +03:00
|
|
|
/************************************************************************/
|
2004-01-16 04:33:43 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Back-end of open() and reopen(). Necessary to have it as a
|
|
|
|
* back-end function so that we can do the thread locking properly
|
|
|
|
* (especially upon reopen).
|
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
static int do_open(int output_id, ompi_output_stream_t *lds)
|
2004-01-16 04:33:43 +03:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int flags;
|
|
|
|
char *filename;
|
|
|
|
|
|
|
|
/* Setup */
|
|
|
|
|
|
|
|
if (!initialized)
|
2004-06-07 19:33:53 +04:00
|
|
|
ompi_output_init();
|
2004-01-16 04:33:43 +03:00
|
|
|
|
|
|
|
/* If output_id == -1, find an available stream, or return
|
2004-06-07 19:33:53 +04:00
|
|
|
OMPI_ERROR */
|
2004-01-16 04:33:43 +03:00
|
|
|
|
|
|
|
if (-1 == output_id) {
|
2004-06-25 01:39:08 +04:00
|
|
|
OMPI_THREAD_LOCK(&mutex);
|
2004-06-07 19:33:53 +04:00
|
|
|
for (i = 0; i < OMPI_OUTPUT_MAX_STREAMS; ++i)
|
2004-01-16 04:33:43 +03:00
|
|
|
if (!info[i].ldi_used)
|
|
|
|
break;
|
2004-06-07 19:33:53 +04:00
|
|
|
if (i >= OMPI_OUTPUT_MAX_STREAMS) {
|
2004-06-25 01:39:08 +04:00
|
|
|
OMPI_THREAD_UNLOCK(&mutex);
|
2004-06-07 19:33:53 +04:00
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
2004-01-16 04:33:43 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Otherwise, we're reopening, so we need to free all previous
|
|
|
|
resources, close files, etc. */
|
|
|
|
|
|
|
|
else {
|
|
|
|
free_descriptor(output_id);
|
|
|
|
i = output_id;
|
|
|
|
}
|
|
|
|
|
2004-05-19 23:52:24 +04:00
|
|
|
/* Special case: if we got NULL for lds, then just use the default
|
|
|
|
verbose */
|
|
|
|
|
|
|
|
if (NULL == lds) {
|
|
|
|
lds = &verbose;
|
|
|
|
}
|
|
|
|
|
2004-01-16 04:33:43 +03:00
|
|
|
/* Got a stream -- now initialize it and open relevant outputs */
|
|
|
|
|
|
|
|
info[i].ldi_used = true;
|
2004-06-25 01:39:08 +04:00
|
|
|
OMPI_THREAD_UNLOCK(&mutex);
|
2004-06-07 19:33:53 +04:00
|
|
|
info[i].ldi_enabled = lds->lds_is_debugging ? (bool) OMPI_ENABLE_DEBUG : true;
|
2004-01-16 04:33:43 +03:00
|
|
|
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;
|
2004-06-07 19:33:53 +04:00
|
|
|
openlog("ompi", LOG_PID, LOG_USER);
|
2004-01-16 04:33:43 +03:00
|
|
|
}
|
|
|
|
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 */
|
|
|
|
|
2004-03-26 13:38:16 +03:00
|
|
|
#if 0
|
2004-06-07 19:33:53 +04:00
|
|
|
filename = ompi_get_tmpdir();
|
2004-01-16 04:33:43 +03:00
|
|
|
#else
|
2004-06-07 19:33:53 +04:00
|
|
|
ompi_output(0, "WARNING: need to implement session dir (%s, %d)\n",
|
2004-03-26 13:38:16 +03:00
|
|
|
__FILE__, __LINE__);
|
2004-02-10 03:09:36 +03:00
|
|
|
filename = malloc(256);
|
2004-01-16 04:33:43 +03:00
|
|
|
strcpy(filename, "/tmp");
|
|
|
|
#endif
|
2004-06-07 19:33:53 +04:00
|
|
|
strcat(filename, "/ompi-");
|
2004-01-16 04:33:43 +03:00
|
|
|
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;
|
2004-06-07 19:33:53 +04:00
|
|
|
return OMPI_ERR_IN_ERRNO;
|
2004-01-16 04:33:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Make the file be close-on-exec to prevent child inheritance
|
|
|
|
problems */
|
|
|
|
|
|
|
|
fcntl(info[i].ldi_fd, F_SETFD, 1);
|
2004-02-10 03:09:36 +03:00
|
|
|
free(filename);
|
2004-01-16 04:33:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Free all the resources associated with a descriptor.
|
|
|
|
*/
|
|
|
|
static void free_descriptor(int output_id)
|
|
|
|
{
|
|
|
|
output_desc_t *ldi;
|
|
|
|
|
2004-06-07 19:33:53 +04:00
|
|
|
if (output_id >= 0 && output_id < OMPI_OUTPUT_MAX_STREAMS &&
|
2004-01-16 04:33:43 +03:00
|
|
|
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)
|
2004-02-10 03:09:36 +03:00
|
|
|
free(ldi->ldi_prefix);
|
2004-01-16 04:33:43 +03:00
|
|
|
ldi->ldi_prefix = NULL;
|
|
|
|
|
|
|
|
if (NULL != ldi->ldi_file_suffix)
|
2004-02-10 03:09:36 +03:00
|
|
|
free(ldi->ldi_file_suffix);
|
2004-01-16 04:33:43 +03:00
|
|
|
ldi->ldi_file_suffix = NULL;
|
|
|
|
|
|
|
|
if (NULL != ldi->ldi_syslog_ident)
|
2004-02-10 03:09:36 +03:00
|
|
|
free(ldi->ldi_syslog_ident);
|
2004-01-16 04:33:43 +03:00
|
|
|
ldi->ldi_syslog_ident = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-14 09:42:24 +03:00
|
|
|
/*
|
|
|
|
* 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)
|
2004-06-07 19:33:53 +04:00
|
|
|
ompi_output_init();
|
2004-01-14 09:42:24 +03:00
|
|
|
|
|
|
|
/* If it's valid, used, and enabled, output */
|
|
|
|
|
2004-06-07 19:33:53 +04:00
|
|
|
if (output_id >= 0 && output_id < OMPI_OUTPUT_MAX_STREAMS &&
|
2004-01-14 09:42:24 +03:00
|
|
|
info[output_id].ldi_used &&
|
|
|
|
info[output_id].ldi_enabled) {
|
|
|
|
ldi = &info[output_id];
|
|
|
|
|
|
|
|
/* Make the formatted string */
|
|
|
|
|
2004-06-25 01:39:08 +04:00
|
|
|
OMPI_THREAD_LOCK(&mutex);
|
2004-06-07 19:33:53 +04:00
|
|
|
str = ompi_vsnprintf(format, arglist);
|
2004-01-14 09:42:24 +03:00
|
|
|
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)
|
2004-02-10 03:09:36 +03:00
|
|
|
free(temp_str);
|
2004-01-14 09:42:24 +03:00
|
|
|
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);
|
2004-06-25 01:39:08 +04:00
|
|
|
OMPI_THREAD_UNLOCK(&mutex);
|
2004-01-14 09:42:24 +03:00
|
|
|
|
2004-02-10 03:09:36 +03:00
|
|
|
free(str);
|
2004-01-14 09:42:24 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2004-06-07 19:33:53 +04:00
|
|
|
* ompi_vsnprintf
|
2004-01-14 09:42:24 +03:00
|
|
|
*
|
|
|
|
* 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...
|
|
|
|
*/
|
2004-06-07 19:33:53 +04:00
|
|
|
static char *ompi_vsnprintf(char *format, va_list arglist)
|
2004-01-14 09:42:24 +03:00
|
|
|
{
|
|
|
|
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;
|
2004-06-07 19:33:53 +04:00
|
|
|
#if OMPI_HAVE_VA_COPY
|
2004-01-14 09:42:24 +03:00
|
|
|
va_copy(arglist2, arglist);
|
2004-06-07 19:33:53 +04:00
|
|
|
#elif OMPI_HAVE_UNDERSCORE_VA_COPY
|
2004-01-14 09:42:24 +03:00
|
|
|
__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. */
|
|
|
|
|
2004-02-10 03:09:36 +03:00
|
|
|
sarg = malloc(len);
|
2004-01-14 09:42:24 +03:00
|
|
|
vsprintf(sarg, format, arglist2);
|
|
|
|
|
|
|
|
/* Return the new string */
|
|
|
|
|
|
|
|
return sarg;
|
|
|
|
}
|