cvs add'd two files for the tprintf() patch...

This commit is contained in:
Marc G. Fournier 1998-08-25 21:43:47 +00:00
parent f62d1253ef
commit 96c4212f99
2 changed files with 435 additions and 0 deletions

View File

@ -0,0 +1,350 @@
/*-------------------------------------------------------------------------
*
* trace.c--
*
* Conditional trace ans logging functions.
*
* Massimo Dal Zotto <dz@cs.unitn.it>
*
*-------------------------------------------------------------------------
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef USE_SYSLOG
#include <syslog.h>
#endif
#include "postgres.h"
#include "miscadmin.h"
#include "utils/trace.h"
#include "libpq/pqsignal.h"
#ifdef USE_SYSLOG
/*
* Global option to control the use of syslog(3) for logging:
*
* 0 stdout/stderr only
* 1 stdout/stderr + syslog
* 2 syslog only
*/
#define UseSyslog pg_options[OPT_SYSLOG]
#define PG_LOG_FACILITY LOG_LOCAL0
#define PG_LOG_IDENT "postgres"
#else
#define UseSyslog 0
#endif
/*
* Trace option names, must match the constants in trace_opts[].
*/
static char *opt_names[] = {
"all",
"verbose",
"query",
"plan",
"parse",
"rewritten",
"parserstats",
"plannerstats",
"executorstats",
"shortlocks", /* currently unused but needed, see lock.c */
"locks",
"userlocks",
"spinlocks",
"notify",
"malloc",
"palloc",
"lock_debug_oidmin",
"lock_debug_relid",
"lock_read_priority", /* lock priority, see lock.c */
"deadlock_timeout", /* deadlock timeout, see proc.c */
"syslog", /* use syslog for error messages */
"hostlookup", /* enable hostname lookup in ps_status */
"showportnumber", /* show port number in ps_status */
"notifyunlock", /* enable unlock of pg_listener after notify */
"notifyhack" /* enable notify hack to remove duplicate tuples */
};
/*
* Array of trace flags which can be set or reset independently.
*/
int pg_options[NUM_PG_OPTIONS] = { 0 };
static int openlog_done = 0;
/*
* Print a timestamp and a message to stdout if the trace flag
* indexed by the flag value is set.
*/
int
tprintf(int flag, const char *fmt, ... )
{
va_list ap;
char line[ELOG_MAXLEN+TIMESTAMP_SIZE+1];
#ifdef USE_SYSLOG
int log_level;
#endif
if ((flag == TRACE_ALL) || (pg_options[TRACE_ALL] > 0)) {
/* uconditional trace or trace all option set */
} else if (pg_options[TRACE_ALL] == 0) {
if ((flag < 0) || (flag >= NUM_PG_OPTIONS) || (!pg_options[flag])) {
return 0;
}
} else if (pg_options[TRACE_ALL] < 0) {
return 0;
}
va_start(ap, fmt);
#ifdef ELOG_TIMESTAMPS
strcpy(line, tprintf_timestamp());
#endif
vsprintf(line+TIMESTAMP_SIZE, fmt, ap);
va_end(ap);
#ifdef USE_SYSLOG
log_level = ((flag == TRACE_ALL) ? LOG_INFO : LOG_DEBUG);
write_syslog(log_level, line+TIMESTAMP_SIZE);
#endif
if (UseSyslog <= 1) {
puts(line);
fflush(stdout);
}
return 1;
}
/*
* Print a timestamp and a message to stderr.
*/
int
eprintf(const char *fmt, ... )
{
va_list ap;
char line[ELOG_MAXLEN+TIMESTAMP_SIZE+1];
va_start(ap, fmt);
#ifdef ELOG_TIMESTAMPS
strcpy(line, tprintf_timestamp());
#endif
vsprintf(line+TIMESTAMP_SIZE, fmt, ap);
va_end(ap);
#ifdef USE_SYSLOG
write_syslog(LOG_ERR, line+TIMESTAMP_SIZE);
#endif
if (UseSyslog <= 1) {
fputs(line, stderr);
fputc('\n', stderr);
fflush(stderr);
}
return 1;
}
#ifdef USE_SYSLOG
/*
* Write a message line to syslog if the syslog option is set.
*/
void
write_syslog(int level, char *line)
{
if (UseSyslog >= 1) {
if (!openlog_done) {
openlog_done = 1;
openlog(PG_LOG_IDENT, LOG_PID|LOG_NDELAY, PG_LOG_FACILITY);
}
syslog(level, "%s", line);
}
}
#endif
#ifdef ELOG_TIMESTAMPS
/*
* Return a timestamp string like "980119.17:25:59.902 [21974] "
*/
char *
tprintf_timestamp()
{
struct timeval tv;
struct tm *time;
time_t tm;
static char timestamp[32], pid[8];
gettimeofday(&tv, DST_NONE);
tm = tv.tv_sec;
time = localtime(&tm);
sprintf(pid, "[%d]", MyProcPid);
sprintf(timestamp, "%02d%02d%02d.%02d:%02d:%02d.%03d %7s ",
time->tm_year, time->tm_mon+1, time->tm_mday,
time->tm_hour, time->tm_min, time->tm_sec,
tv.tv_usec/1000, pid);
return timestamp;
}
#endif
int
option_flag(int flag)
{
if ((flag < 0) || (flag >= NUM_PG_OPTIONS)) {
return 0;
}
return pg_options[flag];
}
int
set_option_flag(int flag, int value)
{
if ((flag < 0) || (flag >= NUM_PG_OPTIONS)) {
return -1;
}
pg_options[flag] = value;
return value;
}
/*
* Parse an option string like "name,name+,name-,name=value".
* Single options are delimited by ',',space,tab,newline or cr.
*/
void
parse_options(char *str)
{
char *s,
*name;
int i,
len,
val,
is_comment;
Assert((sizeof(opt_names)/sizeof(char*)) == NUM_PG_OPTIONS);
str = strdup(str);
for (s=str; *s;) {
is_comment = 0;
name = s;
val = 1;
for (; *s; s++) {
switch (*s) {
case '#':
is_comment = 1;
break;
case '=':
*s++ = '\0';
val = strtol(s, &s, 10);
goto setval;
case '-':
*s++ = '\0';
val = 0;
goto setval;
case '+':
*s++ = '\0';
val = 1;
goto setval;
case ' ':
case ',':
case '\t':
case '\n':
case '\r':
*s = ',';
val = 1;
goto setval;
}
}
setval:
for (; *s; s++) {
if (*s == ',') {
*s++ = '\0';
break;
}
}
len = strlen(name);
if (len == 0) {
continue;
}
for (i=0; i<NUM_PG_OPTIONS; i++) {
if (strncmp(name, opt_names[i], len) == 0) {
pg_options[i] = val;
break;
}
}
if (!is_comment && (i >= NUM_PG_OPTIONS)) {
fprintf(stderr, "invalid option: %s\n", name);
}
}
free(str);
}
#define BUF_SIZE 4096
void
read_pg_options(SIGNAL_ARGS)
{
int fd;
int n;
int verbose;
char buffer[BUF_SIZE];
char c;
char *s,
*p;
sprintf(buffer, "%s/%s", DataDir, "pg_options");
if ((fd = open(buffer, O_RDONLY)) < 0) {
return;
}
if ((n = read(fd, buffer, BUF_SIZE-1)) > 0) {
/* collpse buffer in place removing comments and spaces */
for (s=buffer,p=buffer,c='\0'; s<(buffer+n); ) {
switch (*s) {
case '#':
while ((s < (buffer+n)) && (*s++ != '\n'));
break;
case ' ':
case '\t':
case '\n':
case '\r':
if (c != ',')
c = *p++ = ',';
s++;
break;
default:
c = *p++ = *s++;
break;
}
}
if (c == ',')
p--;
*p = '\0';
verbose = pg_options[TRACE_VERBOSE];
parse_options(buffer);
verbose |= pg_options[TRACE_VERBOSE];
if (verbose || postgres_signal_arg == SIGHUP) {
tprintf(TRACE_ALL, "read_pg_options: %s", buffer);
}
}
close(fd);
}
/*
* Local variables:
* tab-width: 4
* c-indent-level: 4
* c-basic-offset: 4
* End:
*/

85
src/include/utils/trace.h Normal file
View File

@ -0,0 +1,85 @@
/*-------------------------------------------------------------------------
*
* trace.h--
*
* Conditional trace definitions.
*
* Massimo Dal Zotto <dz@cs.unitn.it>
*
*-------------------------------------------------------------------------
*/
#ifndef TRACE_H
#define TRACE_H
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include "postgres.h"
#ifdef ELOG_TIMESTAMPS
char *tprintf_timestamp(void);
#define TIMESTAMP_SIZE 28
#else
#define TIMESTAMP_SIZE 0
#endif
extern int tprintf(int flag, const char *fmt, ...);
extern int eprintf(const char *fmt, ...);
extern int option_flag(int flag);
extern int set_option_flag(int flag, int value);
extern void write_syslog(int level, char *line);
extern void parse_options(char *str);
extern void read_pg_options(SIGNAL_ARGS);
/*
* Trace options, used as index into pg_options.
* Must match the constants in pg_options[].
*/
enum pg_option_enum {
TRACE_ALL, /* 0=trace some, 1=trace all, -1=trace none */
TRACE_VERBOSE,
TRACE_QUERY,
TRACE_PLAN,
TRACE_PARSE,
TRACE_REWRITTEN,
TRACE_PARSERSTATS,
TRACE_PLANNERSTATS,
TRACE_EXECUTORSTATS,
TRACE_SHORTLOCKS, /* currently unused but needed, see lock.c */
TRACE_LOCKS,
TRACE_USERLOCKS,
TRACE_SPINLOCKS,
TRACE_NOTIFY,
TRACE_MALLOC,
TRACE_PALLOC,
TRACE_LOCKOIDMIN,
TRACE_LOCKRELATION,
OPT_LOCKREADPRIORITY, /* lock priority, see lock.c */
OPT_DEADLOCKTIMEOUT, /* deadlock timeout, see proc.c */
OPT_SYSLOG, /* use syslog for error messages */
OPT_HOSTLOOKUP, /* enable hostname lookup in ps_status */
OPT_SHOWPORTNUMBER, /* show port number in ps_status */
OPT_NOTIFYUNLOCK, /* enable unlock of pg_listener after notify */
OPT_NOTIFYHACK, /* enable notify hack to remove duplicate tuples */
NUM_PG_OPTIONS /* must be the last item of enum */
};
extern int pg_options[NUM_PG_OPTIONS];
#define PRINTF(args...) tprintf(TRACE_ALL, args)
#define EPRINTF(args...) eprintf(args)
#define TPRINTF(flag, args...) tprintf(flag, args)
#endif /* TRACE_H */
/*
* Local variables:
* tab-width: 4
* c-indent-level: 4
* c-basic-offset: 4
* End:
*/